这可能是一个愚蠢的问题,但是当你没有传入数组中的元素数量时,sizeof运算符如何知道数组操作数的大小。我知道它不会返回数组中的总元素,而是以字节为单位返回大小,但为了得到它,它仍然必须知道数组何时结束。只是好奇这是如何工作的。
答案 0 :(得分:43)
sizeof
在编译时被解释,编译器知道数组是如何声明的(因此它占用了多少空间)。在动态分配的数组上调用sizeof
可能无法执行您想要的操作,因为(如您所述)未指定数组的结束点。
答案 1 :(得分:22)
你理解这个问题的根本问题可能是因为你混淆了数组和指针,就像许多人一样。但是, 数组不是指针 。 double da[10]
是一个由十double
组成的数组,而不是double*
,当您要求它评估sizeof(da)
时,编译器肯定会知道它。你不会对编译器知道sizeof(double)
?
数组的问题在于它们在许多上下文中自动衰减指向它们的第一个元素(比如它们传递给函数时)。但仍然,数组是数组,指针是指针。
答案 2 :(得分:14)
除了一个案例,sizeof
在编译时就是这样。在编译时,编译器会跟踪对象的完整类型[编辑:好吧,它知道关于对象类型的所有内容 - 无论如何 - 如果类型不完整那么这样做不包括大小,尝试使用sizeof
将失败],sizeof
基本上只是将一条信息从编译器“导出”到正在编译的代码中,因此它基本上是一个常量结果代码。
例外是当sizeof
应用于可变长度数组(VLA) 1 时。当应用于VLA时,sizeof
计算其操作数(否则不会),并生成VLA的实际大小。在这种情况下,结果不是常数。
<子> 1。 VGA正式成为C99中C的一部分,但在此之前,一些编译器支持它们。虽然不是C ++的正式部分,但是一些编译器(例如,g ++)也包含VLA作为C ++的扩展。
答案 3 :(得分:10)
编译器知道应用程序中每种类型的大小,而sizeof
只是请求编译器为您生成该值。
答案 4 :(得分:9)
Sizeof
是一个编译时运算符;它拥有与编译器一样多的信息。 (显然,编译器 知道数组的大小。)
这就是为什么如果你在指针上调用sizeof
你得到指针的宽度,而不是指针所指向的数组的大小。
答案 5 :(得分:5)
Sizeof只能应用于完全定义的类型。编译器要么能够在编译时确定大小(例如,如果你有一个类似int foo [8]的声明;),或者它将能够确定它必须添加代码来跟踪变量的大小-length数组(例如,如果你有一个类似int foo [n + 3]的声明;)。
与此处的其他答案相反,请注意,从C99开始,sizeof()在编译时必须确定 ,因为数组可能是可变长度的。
答案 6 :(得分:3)
如果您在局部变量上使用sizeof
,它会知道您声明了多少个元素。如果你在函数参数上使用sizeof
,它就不知道;它将参数视为指向数组的指针,sizeof
给出指针的大小。
答案 7 :(得分:2)
引自wiki:
这是责任 编译器的作者实现了 sizeof运算符以特定的方式和 对于给定的实现是正确的 语言。 sizeof运算符 必须考虑到 底层的实现 内存分配方案获取 各种数据类型的大小。 sizeof是 通常是编译时运算符,其中 意味着在编译期间,sizeof 并且它的操作数被替换为 结果值。这在很明显 由C生成的汇编语言代码 或C ++编译器。为此原因, sizeof甚至可以作为运营商 虽然它的使用有时看起来像一个 功能调用。
答案 8 :(得分:2)
sizeof operator'知道'所有原子数据类型的大小,因为结构,联合和数组只能通过组装原子类型来构造,它很容易确定任何类型的数组的大小。它使用基本算法来确定复杂类型(在编译期间)。
答案 9 :(得分:2)
sizeof
通常在编译时进行评估。值得注意的例外是C99的可变长度数组。
int main(int argc, char **argv)
{
if (argc > 1)
{
int count = atoi(argv[1]);
int someArray[count];
printf("The size is %zu bytes\n", sizeof someArray);
}
else puts("No");
}
答案 10 :(得分:1)
sizeof在编译时计算。这就是为什么在创建动态数组时,可以通过以下方式创建它。
char * array;
int size;
//Get size somehow.
array = malloc(size*(sizeof(char)));
//现在在编译期间,编译器肯定知道char的大小。因为它必须将它们对准内存。此时,操作系统知道必须分配多少大小。
另一方面,可变长度数组是在堆栈上创建的。但是任何malloc分配的内存都将在堆上创建。
答案 11 :(得分:1)
始终在编译时评估Sizeof。在多传递编译器生成符号表时,编译器必须确定声明的每个符号的大小,以进一步生成中间代码。因此,代码中的所有sizeof引用都会替换确切的值。在中间代码生成阶段,所有运算符,语句都转换为正确的中间代码(ASM /其他格式)。最后,m / c代码生成阶段将其转换为机器代码。
上面讨论的一些讨论,与sizeof相关的动态分配根本不在上下文中。任何对size(* p)的引用,其中p是任何数据类型的指针,编译器只找到* p的数据类型并替换它的大小,而不是去检查已分配块的MCB头以查看分配的是什么内存大小。它不是在运行时。例如double * p; sizeof(* p)仍然可以在不为指针p分配任何内存的情况下完成。怎么可能?