繁体   English   中英

sizeof如何知道操作数数组的大小?

[英]How does sizeof know the size of the operand array?

这可能是一个愚蠢的问题,但是当你没有传入数组中的元素数量时,sizeof运算符如何知道数组操作数的大小。 我知道它不会返回数组中的总元素,而是以字节为单位返回大小,但为了得到它,它仍然必须知道数组何时结束。 只是好奇这是如何工作的。

sizeof在编译时解释,编译器知道数组是如何声明的(因此它占用了多少空间)。 在动态分配的数组上调用sizeof可能无法执行您想要的操作,因为(如您所述)未指定数组的结束点。

你理解这个问题的根本问题可能是因为你混淆了数组和指针,正如许多人所做的那样。 但是, 数组不是指针 double da[10]是十个double的数组,而不是double* ,当你要求它评估sizeof(da)时,编译器当然知道它。 你不会对编译器知道sizeof(double)感到惊讶吗?

数组的问题在于它们在许多上下文中自动衰减指向它们的第一个元素(比如它们传递给函数时)。 但仍然,数组是数组,指针是指针。

除了一个案例, sizeof在编译时就是这样。 在编译时,编译器会跟踪对象的完整类型[编辑:嗯,它知道关于对象类型的所有内容 - 无论如何 - 如果类型不完整,那么不包括大小,尝试使用sizeof将失败], sizeof基本上只是将一条信息从编译器“导出”到正在编译的代码中,因此它在结果代码中基本上是一个常量。

例外情况是将sizeof应用于可变长度数组(VLA) 1 当应用于VLA时, sizeof评估其操作数(否则不会),并生成VLA的实际大小。 在这种情况下,结果不是常数。


1.在V99中,VLA正式成为C的一部分,但在此之前,一些编译器支持它们。 虽然不是C ++的正式部分,但是一些编译器(例如,g ++)也包括VLA作为C ++的扩展。

编译器知道应用程序中每种类型的大小,而sizeof只是请求编译器为您生成该值。

Sizeof是一个编译Sizeof算符; 它拥有与编译器一样多的信息。 (显然编译器确实知道数组的大小)。

这就是为什么如果在指针上调用sizeof ,则获得指针的宽度,而不是指针所指向的数组的大小。

Sizeof只能应用于完全定义的类型。 编译器要么能够在编译时确定大小(例如,如果你有一个类似int foo [8]的声明;),或者它将能够确定它必须添加代码来跟踪变量的大小-length数组(例如,如果你有一个类似int foo [n + 3]的声明;)。

相反,这里其他的答案,请注意,作为C99的,sizeof()会不一定在编译时决定,因为阵列可以是可变长度。

如果您在局部变量上使用sizeof ,它会知道您声明了多少个元素。 如果你在函数参数上使用sizeof ,它就不知道; 它将参数视为指向数组的指针, sizeof指定指针的大小。

来自wiki的引用:

编译器作者有责任以特定的方式实现sizeof运算符,并且对于给定的语言实现是正确的。 sizeof运算符必须考虑底层内存分配方案的实现,以获取各种数据类型的大小。 sizeof通常是编译时运算符,这意味着在编译期间,sizeof及其操作数将被结果值替换。 这在C或C ++编译器生成的汇编语言代码中很明显。 出于这个原因,sizeof有资格作为运算符,即使它的使用有时看起来像函数调用。

sizeof运算符 '知道'所有原子数据类型的大小,因为结构,联合和数组只能通过组装原子类型来构造,因此很容易确定任何类型的数组的大小。 它使用基本算法来确定复杂类型(在编译期间)。

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");
}

sizeof在编译时计算。 这就是为什么在创建动态数组时,可以通过以下方式创建它。

char * array;
int size;
//Get size somehow.
array = malloc(size*(sizeof(char)));

//现在在编译期间,编译器肯定知道char的大小。 因为它必须将它们对准内存。 此时,OS知道它必须分配多少大小。

另一方面, 可变长度数组堆栈上创建。 但是任何malloc分配的内存都将在堆上创建。

始终在编译时评估Sizeof。 在多传递编译器生成符号表时,编译器必须确定声明的每个符号的大小,以进一步生成中间代码。 因此,代码中的所有sizeof引用都会替换确切的值。 在中间代码生成阶段,所有运算符,语句都转换为正确的中间代码(ASM /其他格式)。 最后,m / c代码生成阶段将其转换为机器代码。

上面讨论的一些讨论与sizeof相关的动态分配根本不在上下文中。 任何对size(* p)的引用,其中p是任何数据类型的指针,编译器只找到* p的数据类型并替换它的大小,而不是检查分配块的MCB头以查看分配的内容内存大小。 它不是在运行时。 例如double * p; sizeof(* p)仍然可以在不为指针p分配任何内存的情况下完成。 这怎么可能?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM