How can I print the result of sizeof() at compile time in C?

后端 未结 12 1354
星月不相逢
星月不相逢 2020-11-29 20:47

How can I print the result of sizeof() at compile time in C?

For now I am using a static assert (home brewed based on other web resources) to compare the sizeof() re

12条回答
  •  难免孤独
    2020-11-29 21:46

    This is a generic solution for any C compilers.

    I've realized that if our aim is knowing the value of a sizeof() instead of printing out its value, then we just need to evaluate a few compile time sizeof(X)>?? expressions to narrow down the value.

    The trick is to produce compile time errors when the expressions evaluate to false(zero) or true (non-zero).

    Many standard C constructs can achieve our goal. The duplicate case value trick i described separately is one of them. Another one is through test for division by zero in an initializer which the compiler evaluates at compile time. For example, to get the size of X:

    struct _X {
      int a;
      char c;
      double d;
      float f[30];
    } X;
    

    compile with a few lines:

    #include 
    struct _X {
      int a;
      char c;
      double d;
      float f[30];
    } X;
    int r2=1/(sizeof(X)<170);
    int r3=1/(sizeof(X)<100);
    int r4=1/(sizeof(X)<80);
    int r5=1/(sizeof(X)<60);
    int main()
    {
       return 0;
    }
    

    result

    main.c:17:9: warning: division by zero [-Wdiv-by-zero]
     int r3=1/(sizeof(X)<100);
             ^
    main.c:17:8: error: initializer element is not constant
     int r3=1/(sizeof(X)<100);
            ^
    main.c:18:9: warning: division by zero [-Wdiv-by-zero]
     int r4=1/(sizeof(X)<80);
             ^
    main.c:18:8: error: initializer element is not constant
     int r4=1/(sizeof(X)<80);
            ^
    main.c:19:9: warning: division by zero [-Wdiv-by-zero]
     int r5=1/(sizeof(X)<60);
             ^
    main.c:19:8: error: initializer element is not constant
     int r5=1/(sizeof(X)<60);
            ^
    

    implying sizeof(X)<170 is true (non-zero) but sizeof(X)<100 is false (causing division by zero at compile time). Then we can get the actual value by repeating the test with some other values. e.g

    #include 
    struct _X {
      int a;
      char c;
      double d;
      float f[30];
    } X;
    int r2=1/(sizeof(X)<140);
    int r3=1/(sizeof(X)<137);
    int r4=1/(sizeof(X)<136);
    int r5=1/(sizeof(X)!=136);
    
    int main()
    {
        return 0;
    }
    

    result

    main.c:18:9: warning: division by zero [-Wdiv-by-zero]
     int r4=1/(sizeof(X)<136);
             ^
    main.c:18:8: error: initializer element is not constant
     int r4=1/(sizeof(X)<136);
            ^
    main.c:19:9: warning: division by zero [-Wdiv-by-zero]
     int r5=1/(sizeof(X)!=136);
             ^
    main.c:19:8: error: initializer element is not constant
     int r5=1/(sizeof(X)!=136);
            ^
    

    Hence we know sizeof(X)==136.

    Alternatively, by using the ?: operator, we can make use of more C language constructs that are evaluated at compile time. Visual C++ example using array declaration:

    #include "stdafx.h"
    struct X {
      int a;
      char b[30];
      double d;
      float f[20];
    };
    int a1[sizeof(X)<130?-1:1];
    int a2[sizeof(X)<120?1:-1];
    int a3[sizeof(X)==128?-1:1];
    
    int _tmain(int argc, _TCHAR* argv[]){
      return 0;
    }
    

    result

    1>------ Build started: Project: cpptest, Configuration: Release Win32 ------
    1>  cpptest.cpp
    1>cpptest.cpp(11): error C2118: negative subscript
    1>cpptest.cpp(12): error C2118: negative subscript
    1>cpptest.cpp(13): error C2118: negative subscript
    ========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
    

    implying the sizeof(X) is <130, not <120, and equals to 128

提交回复
热议问题