当{0}
用于初始化对象时,它是什么意思?我无法在任何地方找到任何对{0}
的引用,并且由于大括号,Google搜索无效。
示例代码:
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);
}
没有它,上面的代码将在运行时崩溃。
答案 0 :(得分:297)
这里发生的事情称为聚合初始化。以下是ISO规范第8.5.1节中聚合的(缩写)定义:
聚合是一个数组或类,没有用户声明的构造函数,没有私有或受保护的非静态数据成员,没有基类,也没有虚函数。
现在,使用{0}
来初始化这样的聚合基本上是0
整个事情的一招。这是因为当使用聚合初始化时,您不必指定所有成员,并且规范要求默认初始化所有未指定的成员,这意味着对于简单类型设置为0
。 / p>
以下是规范的相关引用:
如果列表中的初始值设定项少于 聚合,然后每个成员不 明确初始化应为 默认初始化。 例如:
struct S { int a; char* b; int c; }; S ss = { 1, "asdf" };
使用
ss.a
,1
初始化ss.b
"asdf"
和ss.c
,其值为 表达int()
形式,即0
。
您可以找到有关此主题的完整规范here
答案 1 :(得分:87)
需要注意的一点是,这种技术不会将填充字节设置为零。例如:
struct foo
{
char c;
int i;
};
foo a = {0};
不一样:
foo a;
memset(&a,0,sizeof(a));
在第一种情况下,c和i之间的填充字节未初始化。你为什么要关心?好吧,如果您将此数据保存到磁盘或通过网络或其他任何方式发送,则可能存在安全问题。
答案 2 :(得分:19)
请注意,空聚合初始值设定项也有效:
SHELLEXECUTEINFO sexi = {};
char mytext[100] = {};
答案 3 :(得分:11)
回答ShellExecuteEx()
崩溃的原因:您的SHELLEXECUTEINFO
“sexi”结构有很多成员,而您只是初始化其中一些成员。
例如,成员sexi.lpDirectory
可能指向任何位置,但ShellExecuteEx()
仍会尝试使用它,因此您将获得内存访问冲突。
当您包含该行时:
SHELLEXECUTEINFO sexi = {0};
在结构设置的其余部分之前,您要告诉编译器在初始化您感兴趣的特定成员之前将所有结构成员清零。ShellExecuteEx()
知道如果sexi.lpDirectory
为零,应该忽略它。
答案 4 :(得分:7)
我也用它来初始化字符串,例如。
char mytext[100] = {0};
答案 5 :(得分:7)
{0}
是C和C ++中任何(完整对象)类型的有效初始值设定项。这是用于将对象初始化为零的常用习惯用法(请继续阅读以了解其含义)。
对于标量类型(算术类型和指针类型),大括号是不必要的,但它们是明确允许的。引用ISO C标准的N1570 draft,第6.7.9节:
标量的初始值设定项应为单个表达式,可选择用大括号括起来。
它将对象初始化为零(整数为0
,浮点为0.0
,指针为空指针。
对于非标量类型(结构,数组,联合),{0}
指定对象的 first 元素初始化为零。对于包含结构,结构数组等的结构,这是递归应用的,因此第一个标量元素设置为零,适用于类型。与任何初始值设定项一样,未指定的任何元素都设置为零。
可以省略中间括号({
,}
);例如,这两个都是有效的和等效的:
int arr[2][2] = { { 1, 2 }, {3, 4} };
int arr[2][2] = { 1, 2, 3, 4 };
这就是为什么你不必为第一个元素是非标量的类型编写{ { 0 } }
的原因。
所以这个:
some_type obj = { 0 };
是将obj
初始化为零的简便方法,这意味着obj
的每个标量子对象如果是整数则设置为0
,如果是0.0
则为sexi.cbSize
浮点数,如果它是指针,则为空指针。
C ++的规则类似。
在您的特定情况下,由于您要将值分配给SHELLEXECUTEINFO
等等,很明显{ 0 }
是结构或类类型(或者可能是联合,但可能不是),所以并非所有这些都适用,但正如我所说memset
是一种常见的习惯用语,可用于更一般的情况。
这 not (必然)等同于使用0.0
将对象的表示设置为all-bits-zero。浮点{ 0 }
和空指针都不一定表示为全比特零,并且{{1}}初始化器不一定将填充字节设置为任何特定值。但是,在大多数系统中,它可能会产生相同的效果。
答案 6 :(得分:3)
自从我使用c / c ++但是IIRC以来已经有一段时间了,同样的快捷方式也可以用于数组。
答案 7 :(得分:2)
我一直在想,为什么你应该使用像
这样的东西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系统上使用uccntu 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”部分是内存部分,在调用 main
之前设置为零,请参阅wikipedia on .bss。
如果您将上面的代码更改为:
} my_zero_struct = { 0 };
然后,至少使用ubuntu 12.04.2上的gcc 4.6.3编译器,生成的“check”可执行文件看起来完全; my_zero_struct
仍位于.bss
部分,因此在调用main
之前,它会自动初始化为零。
评论中的提示,memset
可能初始化“完整”结构也不是一种改进,因为.bss
部分被完全清除,这也意味着“完整”结构被设置为零。
可能是C语言标准没有提到这一点,但在现实世界的C编译器中,我从未见过不同的行为。
答案 8 :(得分:0)
用语法糖将整个结构初始化为空/零/空值。
长版
SHELLEXECUTEINFO sexi;
sexi.cbSize = 0;
sexi.fMask = 0;
sexi.hwnd = NULL;
sexi.lpVerb = NULL;
sexi.lpFile = NULL;
sexi.lpParameters = NULL;
sexi.lpDirectory = NULL;
sexi.nShow = nShow;
sexi.hInstApp = 0;
sexi.lpIDList = NULL;
sexi.lpClass = NULL;
sexi.hkeyClass = 0;
sexi.dwHotKey = 0;
sexi.hMonitor = 0;
sexi.hProcess = 0;
简短版本
SHELLEXECUTEINFO sexi = {0};
难道不是那么容易吗?
它也很不错,因为:
ZeroMemory
答案 9 :(得分:-5)
{0}是匿名数组,其元素为0。
这用于使用0初始化数组的一个或所有元素。
e.g。 int arr [8] = {0};
在这种情况下,arr的所有元素都将初始化为0。