【问题标题】:Does sizeof evaluate at compile-time or runtime?sizeof 是在编译时还是运行时评估?
【发布时间】:2012-06-26 03:12:07
【问题描述】:

我对@9​​87654321@运营商的评估时间感到困惑。
sizeof 运算符何时被评估?

它的评估时间(编译时或运行时)是否取决于语言(C?C++?)?

如果在 C++ 中运行时创建的对象,我们可以使用sizeof 吗?

【问题讨论】:

    标签: c++ c operators


    【解决方案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,而不是 proofalloca 不需要明确的释放/范围。生成的代码(或多或少)与 VLA 相同 - 移动堆栈指针 + 在跨页边界时探测堆栈内存。我个人在元编程(temapltes 等)中非常积极地使用sizeof,我想100% 确定sizeof 中的任何内容都不会在运行时被评估。
        • @valdo,不需要释放范围,但也没有提供。我发现分配一直持续到函数终止的想法非常违反直觉。我在 C 中使用宏进行了很多元编程,到目前为止,我还没有因为 VLA 而遇到过大问题。并且不要夸大 VLA 的 sizeof 的运行时方面。它只是对一些包含大小的隐藏变量的评估。但是编译器正在为您完成工作,并且可以在许多地方进行优化。
        • @Jens Gustedt:alloca 不提供“释放范围”,原因与 VLA 不提供此功能完全相同。在不影响随后分配的堆栈变量的情况下,可能不会释放堆栈变量(固定大小或非固定大小)。所以你说持续到函数终止的(显式)分配是违反直觉的,OTOH我相信强制编译时运算符在运行时默默地做事情是违反直觉的。它不仅仅是一个“隐藏变量”,有时这个变量需要评估。比如函数调用的 retval 的sizeof(不正常调用)。
        猜你喜欢
        • 2011-02-06
        • 2020-05-18
        • 2013-09-17
        • 1970-01-01
        • 1970-01-01
        • 2013-08-29
        • 2014-12-21
        • 1970-01-01
        • 2017-05-26
        相关资源
        最近更新 更多