当 {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 回答
这里发生的事情叫做 aggregate 初始化 . 以下是ISO规范第8.5.1节中聚合的(缩写)定义:
现在,使用
{0}
来初始化像这样的聚合基本上是整个事情的一个技巧 . 这是因为当使用聚合初始化 you don't have to specify all the members 时,规范要求默认初始化所有未指定的成员,这意味着对于简单类型设置为0
.以下是该规范的相关引用:
你可以找到关于这个主题的完整规范here
需要注意的一点是,这种技术不会将填充字节设置为零 . 例如:
不一样:
在第一种情况下,c和i之间的填充字节是未初始化的 . 你为什么要关心?好吧,如果您将此数据保存到磁盘或通过网络或其他任何方式发送,则可能存在安全问题 .
请注意,空聚合初始值设定项也可以:
回答
ShellExecuteEx()
崩溃的原因:你的SHELLEXECUTEINFO
"sexi" struct有很多成员,你只是初始化其中的一些 .例如,成员
sexi.lpDirectory
可能指向任何位置,但ShellExecuteEx()
仍将尝试使用它,因此您将获得内存访问冲突 .当您包含该行时:
在你的结构设置的其余部分之前,你告诉编译器在初始化你感兴趣的特定成员之前将结构成员清零 .
ShellExecuteEx()
知道如果sexi.lpDirectory
为零,它应该忽略它 .我也用它来初始化字符串,例如 .
{0}
是C和C中任何(完整对象)类型的有效初始值设定项 . 这是用于将对象初始化为零的常用习惯用法(请继续阅读以了解其含义) .对于标量类型(算术和指针类型),大括号是不必要的,但它们是明确允许的 . 引用ISO C标准的N1570 draft,第6.7.9节:
它将对象初始化为零(整数为
0
,浮点为0.0
,指针为空指针) .对于非标量类型(结构,数组,联合),
{0}
指定将对象的第一个元素初始化为零 . 对于包含结构,结构数组等的结构,这是递归应用的,因此第一个标量元素设置为零,适用于类型 . 与任何初始化程序一样,未指定的任何元素都设置为零 .中间括号(
{
,}
)可以省略;例如,这些都是有效的和等效的:这就是为什么你不必为第一个元素是非标量的类型编写
{ { 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 }
初始化程序也不具有相同的效果 .自从我在c / c工作但是IIRC已经有一段时间了,同样的快捷方式也可以用于数组 .
我一直想知道, why 你应该使用类似的东西
这是一个测试用例来解释:
check.c
我用
gcc -O2 -o check check.c
编译然后用readelf -s check | sort -k 2
输出符号表(这是在x64系统上的ubuntu 12.04.2上使用gcc 4.6.3) . 摘抄:这里的重要部分是
my_zero_struct
在__bss_start
之后 . C程序中的".bss"部分是内存的一部分设为零 beforemain
被调用见wikipedia on .bss .如果您将上面的代码更改为:
然后生成的"check"可执行文件至少与ubuntu 12.04.2上的gcc 4.6.3编译器相同 exactly ;
my_zero_struct
仍然在.bss
部分,因此在调用main
之前它将自动初始化为零 .注释中的提示,
memset
可能初始化"full"结构也不是一种改进,因为.bss
部分被完全清除,这也意味着"full"结构被设置为零 .它 might 是C语言标准没有提到任何这个,但在现实世界的C编译器中我从未见过不同的行为 .
{0}是 anonymous array ,其元素为0 .
这用于 initialize one or all elements of array with 0.
例如int arr [8] = {0};
在这种情况下,arr的所有元素都将初始化为0 .