当{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);
}

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


当前回答

{0}是C和c++中任何(完整对象)类型的有效初始化式。这是用于将对象初始化为0的常用习语(请继续阅读以了解这意味着什么)。

对于标量类型(算术类型和指针类型),花括号是不必要的,但显式地允许它们。引用ISO C标准的N1570草案,第6.7.9节:

标量的初始化式应该是一个单独的表达式,可以选择用大括号括起来。

它将对象初始化为0(整数为0,浮点数为0.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初始化为0的一种简写方法,这意味着obj的每个标量子对象如果是整数则设置为0,如果是浮点则设置为0.0,如果是指针则设置为空指针。

这些规则与c++类似。

在你的特殊情况下,因为你给sexi赋值。cbSize等等,显然SHELLEXECUTEINFO是一个结构体或类类型(也可能是一个联合,但也可能不是),所以不是所有这些都适用,但正如我所说,{0}是一个可以在更一般的情况下使用的常用习语。

这(不一定)等同于使用memset将对象的表示设置为全位零。浮点0.0和空指针都不一定表示为全位0,{0}初始化式也不一定将填充字节设置为任何特定的值。不过,在大多数系统上,它可能具有相同的效果。

其他回答

关于ShellExecuteEx()崩溃的原因:你的SHELLEXECUTEINFO "sexi"结构体有很多成员,你只初始化了其中的一些成员。

例如,sexi成员。lpDirectory可以指向任何地方,但ShellExecuteEx()仍将尝试使用它,因此您将得到内存访问冲突。

当你包括这行:

SHELLEXECUTEINFO sexi = {0};

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

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

struct foo
{
    char c;
    int  i;
};

foo a = {0};

并不等同于:

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

在第一种情况下,c和i之间的pad字节是未初始化的。你为什么关心这个?好吧,如果你把数据保存到磁盘上或者通过网络发送,你可能会有安全问题。

我也用它来初始化字符串。

char mytext[100] = {0};

{0}是一个匿名数组,其元素为0。

这个函数用于初始化数组中的一个或所有元素。

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

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

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