让我们考虑 int array[] = {2,33,4,56,7,8}; //案例A
如果 sizeof() 检查 '\0' 作为 char[] 数组的结尾!sizeof(array) 检查什么作为标记值以查找 int 数组的结尾,因此在案例 A 中数组的大小?
如果我要实现 sizeof (intArray) ,就没有访问标记值信息的自由吗?
sizeof
不检查任何东西。它只是看起来像一个函数调用,但它实际上是一个运算符,一个编译器技巧,用于在编译时插入编译器已知的大小。
以下是sizeof
与 C 数组交互的方式:当您声明一个数组时,您将其大小指定为常量、运行时整数表达式,或者通过提供一定数量的值放入数组中来隐式指定。
当在编译时知道元素的数量时,编译器将替换sizeof(array)
为实际数量。当直到运行时才知道元素的数量时,编译器会准备一个特定于实现的特殊存储位置,并将大小存储在那里。正在运行的程序将需要此信息来清理堆栈。编译器还让实现的运行时部分知道这些隐藏信息,sizeof
以返回正确的值。
我认为您将'\0'
最后带有(空终止符)的字符串文字与一般的数组混淆了。数组具有编译器1已知的编译时长度。sizeof
是一个运算符,它根据数组长度和数组的基本类型给出大小。
因此,当有人这样做时int a[] = {1, 2, 3};
,最后没有添加空终止字符,并且编译器将元素的数量推导出为 3。在sizeof(int)
= 4 的平台上,您将得到sizeof(a)
12。
混淆是因为对于char b[] = "abc";
,元素计数将是 4,因为所有字符串文字都有一个'\0'
自动放置的即它们自动以空值终止。不是sizeof
操作员对此进行检查;它只是给出,4 * sizeof(char)
因为对于sizeof
所有重要的是编译时数组长度,即 4 = 1 + 由于 C 中字符串文字的性质而在字符串文字中明确说明的字符数。
但是,不是由字符串文字初始化但具有字符文字的字符数组没有这个怪癖。因此 if char c[] = {'a', 'b', 'c'};
,sizeof(c)
将返回 3 而不是 4 因为它不是字符串文字并且没有空终止字符。再次 sizeof 运算符(不是函数)在编译时执行此推导2。
最后,如何实现 sizeof 运算符本身来执行此操作,是标准未规定的实现细节。标准谈论条件和结果。它们是如何通过实现实现的,与标准无关(或除实现它的开发人员之外的任何人)。
1 C99 引入了可变长度数组 (VLA),它允许数组具有动态大小。
2 仅对于 VLA,sizeof
运算符及其操作数在运行时进行评估
sizeof
不是一个函数,而是一个编译时运算符,它被替换为变量的大小。在真正的数组(不是指针)的情况下,它被替换为数组内容的字节大小,因为它在编译时就知道了;
尝试以下方法来说服自己:
void print_size(int[] array)
{
printf("%u\n", sizeof(array)); //Prints 4 (= sizeof(int*))
//May print 8 on 64b architectures
}
int main()
{
int array[] = {2,33,4,56,7,8};
printf("%u\n", sizeof(array)); //Prints 24 (= 6*sizeof(int))
print_size(array);
return 0;
}
这是因为,在 内部main
,编译器知道 array 是一个 6int
的数组,而函数print_size
可以用任何数组调用,所以它的大小是事先不知道的:它被当作 int* 处理(除了我不确定它是否是左值)