【发布时间】:2012-06-26 03:12:07
【问题描述】:
我对@987654321@运营商的评估时间感到困惑。
sizeof 运算符何时被评估?
它的评估时间(编译时或运行时)是否取决于语言(C?C++?)?
如果在 C++ 中运行时创建的对象,我们可以使用sizeof 吗?
【问题讨论】:
我对@987654321@运营商的评估时间感到困惑。
sizeof 运算符何时被评估?
它的评估时间(编译时或运行时)是否取决于语言(C?C++?)?
如果在 C++ 中运行时创建的对象,我们可以使用sizeof 吗?
【问题讨论】:
在 C 中它并不总是一个编译时操作,如下代码所示:
#include <stdio.h>
#include <stdint.h>
int main(void) {
int x;
scanf("%d", &x); // Value X is not known until run-time
uint16_t data[x]; // VLA: has flexible size depending on input
printf("Value x is: %d\nSize is: %zu\n", x, sizeof(data));
// sizeof produces proper results at runtime
return 0;
}
数组data的大小直到运行时才知道,sizeof操作符仍然可以正常工作。
这是 C++ 选择不支持 VLA 的几个原因之一。
【讨论】:
编译时间,因为它是在编译时计算大小。“编译时间”是您构建代码的时间——编译器将您的源代码转换为 IL 的时间。
【讨论】:
几乎总是编译时间。但您可能会对以下示例感兴趣:
char c[100];
sizeof(c); // 100
char* d = malloc(100);
sizeof(d); //probably 4 or 8. tells you the size of the pointer!
BaseClass* b = new DerivedClass();
sizeof(b); //probably 4 or 8 as above.
void foo(char[100] x) {
sizeof(x); //probably 4 or 8. I hate this. Don't use this style for this reason.
}
struct Foo {
char a[100];
char b[200];
};
sizeof(struct Foo); //probably 300. Technically architecture dependent but it will be
//the # of bytes the compiler needs to make a Foo.
struct Foo foo;
sizeof(foo); //same as sizeof(struct Foo)
struct Foo* fooP;
sizeof(fooP); //probably 4 or 8
class ForwardDeclaredClass;
ForwardDeclaredClass* p;
sizeof(p); //4 or 8
ForwardDeclaredClass fdc; //compile time error. Compiler
//doesn't know how many bytes to allocate
sizeof(ForwardDeclaredClass); //compile time error, same reason
【讨论】:
在几乎所有情况下,sizeof 的评估都是基于静态类型信息(基本上是在编译时)。
C99 的可变长度数组 (VLA) 是一个例外(我认为是唯一一个)。
【讨论】:
alloca)要好得多。
sizeof 在执行时动态调整大小的对象必须在执行时进行评估似乎很正常。与alloca(甚至没有标准化且没有范围)或malloc等其他机制相比,两者都不知道他们创建的对象的大小并不是很有帮助。
alloca 不需要明确的释放/范围。生成的代码(或多或少)与 VLA 相同 - 移动堆栈指针 + 在跨页边界时探测堆栈内存。我个人在元编程(temapltes 等)中非常积极地使用sizeof,我想100% 确定sizeof 中的任何内容都不会在运行时被评估。
sizeof 的运行时方面。它只是对一些包含大小的隐藏变量的评估。但是编译器正在为您完成工作,并且可以在许多地方进行优化。
alloca 不提供“释放范围”,原因与 VLA 不提供此功能完全相同。在不影响随后分配的堆栈变量的情况下,可能不会释放堆栈变量(固定大小或非固定大小)。所以你说持续到函数终止的(显式)分配是违反直觉的,OTOH我相信强制编译时运算符在运行时默默地做事情是违反直觉的。它不仅仅是一个“隐藏变量”,有时这个变量需要评估。比如函数调用的 retval 的sizeof(不正常调用)。