sizeof 是在编译时还是运行时评估?
Posted
技术标签:
【中文标题】sizeof 是在编译时还是运行时评估?【英文标题】:Does sizeof evaluate at compile-time or runtime? 【发布时间】:2012-06-26 03:12:07 【问题描述】:我对@987654321@运营商的评估时间感到困惑。 sizeof 运算符何时被评估?
它的评估时间(编译时或运行时)是否取决于语言(C?C++?)?
如果在 C++ 中运行时创建的对象,我们可以使用sizeof
吗?
【问题讨论】:
【参考方案1】:在 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 的几个原因之一。
【讨论】:
【参考方案2】:编译时间,因为它是在编译时计算大小。“编译时间”是您构建代码的时间——编译器将您的源代码转换为 IL 的时间。
【讨论】:
【参考方案3】:几乎总是编译时间。但您可能会对以下示例感兴趣:
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
【讨论】:
也许“void foo(char[100] x)”实际上应该是“void foo(char x[100])”? VLA 怎么样?【参考方案4】:在几乎所有情况下,sizeof
的评估都是基于静态类型信息(基本上是在编译时)。
C99 的可变长度数组 (VLA) 是一个例外(我认为是唯一一个)。
【讨论】:
很好地证明了 VLA 是多么荒谬的变态。恕我直言,显式可变长度堆栈消耗(alloca
)要好得多。
@valdo,我看不出这应该证明什么。 sizeof
在执行时动态调整大小的对象必须在执行时进行评估似乎很正常。与alloca
(甚至没有标准化且没有范围)或malloc
等其他机制相比,两者都不知道他们创建的对象的大小并不是很有帮助。
@Jens Gustedt:抱歉,我的意思是 example,而不是 proof。 alloca
不需要明确的释放/范围。生成的代码(或多或少)与 VLA 相同 - 移动堆栈指针 + 在跨页边界时探测堆栈内存。我个人在元编程(temapltes 等)中非常积极地使用sizeof
,我想100% 确定sizeof
中的任何内容都不会在运行时被评估。
@valdo,不需要释放范围,但也没有提供。我发现分配一直持续到函数终止的想法非常违反直觉。我在 C 中使用宏进行了很多元编程,到目前为止,我还没有因为 VLA 而遇到过大问题。并且不要夸大 VLA 的 sizeof
的运行时方面。它只是对一些包含大小的隐藏变量的评估。但是编译器正在为您完成工作,并且可以在许多地方进行优化。
@Jens Gustedt:alloca
不提供“释放范围”,原因与 VLA 不提供此功能完全相同。在不影响随后分配的堆栈变量的情况下,可能不会释放堆栈变量(固定大小或非固定大小)。所以你说持续到函数终止的(显式)分配是违反直觉的,OTOH我相信强制编译时运算符在运行时默默地做事情是违反直觉的。它不仅仅是一个“隐藏变量”,有时这个变量需要评估。比如函数调用的 retval 的sizeof
(不正常调用)。以上是关于sizeof 是在编译时还是运行时评估?的主要内容,如果未能解决你的问题,请参考以下文章