没有明确长度的 sizeof 数组
sizeof array without explicit length
sizeof
是否可以安全地用于已声明但未在方括号内指定明确大小但已在声明中初始化的数组?
考虑以下代码:
unsigned int arr[] = { 1, 2, 3 };
size_t bytes = sizeof arr;
如果在没有任何特殊编译器标志的情况下使用 clang-800.0.42.1 在 macOS 上编译,这会产生 12
的预期结果。
但是 C 标准(或 any C 标准,如果它们在这方面有所不同)是否保证是这种情况?或者我是否必须像 unsigned int arr[3]
一样声明它才能成为 "sane"?
是的,如果未指定大小,标准保证数组元素计数将等于数组初始值设定项中的元素数。看
C11 standard draft 6.7.9p22 and 6.7.9p25:
If an array of unknown size is initialized, its size is determined by
the largest indexed element with an explicit initializer. The array
type is completed at the end of its initializer list.
EXAMPLE 2 The declaration
int x[] = { 1, 3, 5 };
defines and initializes x
as a one-dimensional array object that has three elements, as no size was specified and there are three initializers.
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)
被定义但是是该指针的大小并且 而不是 原始数组的大小。
sizeof
是否可以安全地用于已声明但未在方括号内指定明确大小但已在声明中初始化的数组?
考虑以下代码:
unsigned int arr[] = { 1, 2, 3 };
size_t bytes = sizeof arr;
如果在没有任何特殊编译器标志的情况下使用 clang-800.0.42.1 在 macOS 上编译,这会产生 12
的预期结果。
但是 C 标准(或 any C 标准,如果它们在这方面有所不同)是否保证是这种情况?或者我是否必须像 unsigned int arr[3]
一样声明它才能成为 "sane"?
是的,如果未指定大小,标准保证数组元素计数将等于数组初始值设定项中的元素数。看 C11 standard draft 6.7.9p22 and 6.7.9p25:
If an array of unknown size is initialized, its size is determined by the largest indexed element with an explicit initializer. The array type is completed at the end of its initializer list.
EXAMPLE 2 The declaration
int x[] = { 1, 3, 5 };
defines and initializes
x
as a one-dimensional array object that has three elements, as no size was specified and there are three initializers.
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)
被定义但是是该指针的大小并且 而不是 原始数组的大小。