可以sizeof
安全地使用已声明但未在方括号内指定显式大小但在声明中初始化的数组吗?
请考虑以下代码:
unsigned int arr[] = { 1, 2, 3 };
size_t bytes = sizeof arr;
如果在没有任何特殊编译器标志的情况下使用clang-800.0.42.1在macOS上编译,则会产生12
的预期结果。
但是C标准(或者任何 C标准,如果它们有不同的话)是否保证了这种情况?或者我必须声明它像unsigned int arr[3]
,以便它是#34;理智"?
答案 0 :(得分:8)
是的,该标准保证在没有指定大小的情况下,数组元素计数将等于数组初始值设定项中的元素数。看到 C11 standard draft 6.7.9p22和6.7.9p25:
如果初始化未知大小的数组,则其大小由确定 具有显式初始值设定项的最大索引元素。阵列 type在其初始化列表的末尾完成。
示例2声明
int x[] = { 1, 3, 5 };
将
x
定义并初始化为具有三个元素的一维数组对象,因为没有指定大小且有三个初始值设定项。
答案 1 :(得分:1)
unsigned int arr[] = { 1, 2, 3 };
实际上定义了一个完整的数组。数组的大小在此编译单元中是已知的,并且是n * sizeof(type),其中n是初始化列表中的元素数(此处为3),type是基础对象类型(此处为unsigned int
)。
这意味着sizeof(arr)
与arr
在同一范围内定义并具有预期值。
完全不同的是extern int arr[];
。这将是一个简单的声明,该名称的数组将在另一个编译单元中提供,但编译器无法知道其大小。在这种情况下,使用sizeof(arr)
将是一个错误。
仅仅声明的另一个例子是
void func(int arr[]) {
...
}
这里再次编译器只知道该函数将接收一个int数组,但再次无法知道它的大小。但是这里编译器生成一个指针,它将接收数组的地址并定义sizeof(arr)
,但是该指针的大小和不原始数组的大小。