首页 文章

初始化对象时{0}意味着什么?

提问于
浏览
244

{0} 用于初始化对象时,它是什么意思?我无法在任何地方找到任何对 {0} 的引用,并且由于大括号,谷歌搜索没有帮助 .

示例代码:

SHELLEXECUTEINFO sexi = {0}; // what does this do?
sexi.cbSize = sizeof(SHELLEXECUTEINFO);
sexi.hwnd = NULL;
sexi.fMask = SEE_MASK_NOCLOSEPROCESS;
sexi.lpFile = lpFile.c_str();
sexi.lpParameters = args;
sexi.nShow = nShow;

if(ShellExecuteEx(&sexi))
{
    DWORD wait = WaitForSingleObject(sexi.hProcess, INFINITE);
    if(wait == WAIT_OBJECT_0)
        GetExitCodeProcess(sexi.hProcess, &returnCode);
}

没有它,上面的代码将在运行时崩溃 .

9 回答

  • 294

    这里发生的事情叫做 aggregate 初始化 . 以下是ISO规范第8.5.1节中聚合的(缩写)定义:

    聚合是一个数组或类,没有用户声明的构造函数,没有私有或受保护的非静态数据成员,没有基类,也没有虚函数 .

    现在,使用 {0} 来初始化像这样的聚合基本上是整个事情的一个技巧 . 这是因为当使用聚合初始化 you don't have to specify all the members 时,规范要求默认初始化所有未指定的成员,这意味着对于简单类型设置为 0 .

    以下是该规范的相关引用:

    如果列表中的初始值设定项少于聚合中的成员,则未明确初始化的每个成员都应默认初始化 . 示例:struct S {int a; char * b; int c; };
    S ss = {1,“asdf”};
    使用“asdf”初始化ss.a,使用“asdf”初始化ss.b,使用int()形式的表达式的值初始化ss.c,即0 .

    你可以找到关于这个主题的完整规范here

  • 19

    需要注意的一点是,这种技术不会将填充字节设置为零 . 例如:

    struct foo
    {
        char c;
        int  i;
    };
    
    foo a = {0};
    

    不一样:

    foo a;
    memset(&a,0,sizeof(a));
    

    在第一种情况下,c和i之间的填充字节是未初始化的 . 你为什么要关心?好吧,如果您将此数据保存到磁盘或通过网络或其他任何方式发送,则可能存在安全问题 .

  • 2

    请注意,空聚合初始值设定项也可以:

    SHELLEXECUTEINFO sexi = {};
    char mytext[100] = {};
    
  • 11

    回答 ShellExecuteEx() 崩溃的原因:你的 SHELLEXECUTEINFO "sexi" struct有很多成员,你只是初始化其中的一些 .

    例如,成员 sexi.lpDirectory 可能指向任何位置,但 ShellExecuteEx() 仍将尝试使用它,因此您将获得内存访问冲突 .

    当您包含该行时:

    SHELLEXECUTEINFO sexi = {0};
    

    在你的结构设置的其余部分之前,你告诉编译器在初始化你感兴趣的特定成员之前将结构成员清零 . ShellExecuteEx() 知道如果 sexi.lpDirectory 为零,它应该忽略它 .

  • -5

    我也用它来初始化字符串,例如 .

    char mytext[100] = {0};
    
  • 7

    {0} 是C和C中任何(完整对象)类型的有效初始值设定项 . 这是用于将对象初始化为零的常用习惯用法(请继续阅读以了解其含义) .

    对于标量类型(算术和指针类型),大括号是不必要的,但它们是明确允许的 . 引用ISO C标准的N1570 draft,第6.7.9节:

    标量的初始值设定项应为单个表达式,可选择用大括号括起来 .

    它将对象初始化为零(整数为 0 ,浮点为 0.0 ,指针为空指针) .

    对于非标量类型(结构,数组,联合), {0} 指定将对象的第一个元素初始化为零 . 对于包含结构,结构数组等的结构,这是递归应用的,因此第一个标量元素设置为零,适用于类型 . 与任何初始化程序一样,未指定的任何元素都设置为零 .

    中间括号( {} )可以省略;例如,这些都是有效的和等效的:

    int arr[2][2] = { { 1, 2 }, {3, 4} };
    
    int arr[2][2] = { 1, 2, 3, 4 };
    

    这就是为什么你不必为第一个元素是非标量的类型编写 { { 0 } } 的原因 .

    所以这:

    some_type obj = { 0 };
    

    是将 obj 初始化为零的简写方法,这意味着 obj 的每个标量子对象如果是整数则设置为 0 ,如果's floating-point, or a null pointer if it'是指针则为 0.0 .

    C的规则相似 .

    在您的特定情况下,由于您将值分配给 sexi.cbSize 等等,很明显 SHELLEXECUTEINFO 是结构或类类型(或者可能是联合,但可能不是),因此并非所有这些都适用,但正如我所说 { 0 } 是一种常见的习语,可以在更一般的情况下使用 .

    这不一定(必然)等同于使用 memset 将对象的表示设置为all-bits-zero . 浮点 0.0 和空指针都不一定表示为全比特零,而 { 0 } 初始化程序也不具有相同的效果 .

  • 7

    自从我在c / c工作但是IIRC已经有一段时间了,同样的快捷方式也可以用于数组 .

  • 87

    我一直想知道, why 你应该使用类似的东西

    struct foo bar = { 0 };
    

    这是一个测试用例来解释:

    check.c

    struct f {
        int x;
        char a;
    } my_zero_struct;
    
    int main(void)
    {
        return my_zero_struct.x;
    }
    

    我用 gcc -O2 -o check check.c 编译然后用 readelf -s check | sort -k 2 输出符号表(这是在x64系统上的ubuntu 12.04.2上使用gcc 4.6.3) . 摘抄:

    59: 0000000000601018     0 NOTYPE  GLOBAL DEFAULT  ABS __bss_start
    48: 0000000000601018     0 NOTYPE  GLOBAL DEFAULT  ABS _edata
    25: 0000000000601018     0 SECTION LOCAL  DEFAULT   25 
    33: 0000000000601018     1 OBJECT  LOCAL  DEFAULT   25 completed.6531
    34: 0000000000601020     8 OBJECT  LOCAL  DEFAULT   25 dtor_idx.6533
    62: 0000000000601028     8 OBJECT  GLOBAL DEFAULT   25 my_zero_struct
    57: 0000000000601030     0 NOTYPE  GLOBAL DEFAULT  ABS _end
    

    这里的重要部分是 my_zero_struct__bss_start 之后 . C程序中的".bss"部分是内存的一部分设为零 before main 被调用见wikipedia on .bss .

    如果您将上面的代码更改为:

    } my_zero_struct = { 0 };
    

    然后生成的"check"可执行文件至少与ubuntu 12.04.2上的gcc 4.6.3编译器相同 exactly ; my_zero_struct 仍然在 .bss 部分,因此在调用 main 之前它将自动初始化为零 .

    注释中的提示, memset 可能初始化"full"结构也不是一种改进,因为 .bss 部分被完全清除,这也意味着"full"结构被设置为零 .

    might 是C语言标准没有提到任何这个,但在现实世界的C编译器中我从未见过不同的行为 .

  • 3

    {0}是 anonymous array ,其元素为0 .

    这用于 initialize one or all elements of array with 0.

    例如int arr [8] = {0};

    在这种情况下,arr的所有元素都将初始化为0 .

相关问题