Static assert in C

前端 未结 12 622
感情败类
感情败类 2020-11-22 16:22

What\'s the best way to achieve compile time static asserts in C (not C++), with particular emphasis on GCC?

12条回答
  •  栀梦
    栀梦 (楼主)
    2020-11-22 17:06

    From Perl, specifically perl.h line 3455 ( is included beforehand):

    /* STATIC_ASSERT_DECL/STATIC_ASSERT_STMT are like assert(), but for compile
       time invariants. That is, their argument must be a constant expression that
       can be verified by the compiler. This expression can contain anything that's
       known to the compiler, e.g. #define constants, enums, or sizeof (...). If
       the expression evaluates to 0, compilation fails.
       Because they generate no runtime code (i.e.  their use is "free"), they're
       always active, even under non-DEBUGGING builds.
       STATIC_ASSERT_DECL expands to a declaration and is suitable for use at
       file scope (outside of any function).
       STATIC_ASSERT_STMT expands to a statement and is suitable for use inside a
       function.
    */
    #if (defined(static_assert) || (defined(__cplusplus) && __cplusplus >= 201103L)) && (!defined(__IBMC__) || __IBMC__ >= 1210)
    /* static_assert is a macro defined in  in C11 or a compiler
       builtin in C++11.  But IBM XL C V11 does not support _Static_assert, no
       matter what  says.
    */
    #  define STATIC_ASSERT_DECL(COND) static_assert(COND, #COND)
    #else
    /* We use a bit-field instead of an array because gcc accepts
       'typedef char x[n]' where n is not a compile-time constant.
       We want to enforce constantness.
    */
    #  define STATIC_ASSERT_2(COND, SUFFIX) \
        typedef struct { \
            unsigned int _static_assertion_failed_##SUFFIX : (COND) ? 1 : -1; \
        } _static_assertion_failed_##SUFFIX PERL_UNUSED_DECL
    #  define STATIC_ASSERT_1(COND, SUFFIX) STATIC_ASSERT_2(COND, SUFFIX)
    #  define STATIC_ASSERT_DECL(COND)    STATIC_ASSERT_1(COND, __LINE__)
    #endif
    /* We need this wrapper even in C11 because 'case X: static_assert(...);' is an
       error (static_assert is a declaration, and only statements can have labels).
    */
    #define STATIC_ASSERT_STMT(COND)      STMT_START { STATIC_ASSERT_DECL(COND); } STMT_END
    

    If static_assert is available (from ), it is used. Otherwise, if the condition is false, a bit-field with a negative size is declared, which causes compilation to fail.

    STMT_START / STMT_END are macros expanding to do / while (0), respectively.

提交回复
热议问题