如何测试 _Static_assert 是否已定义?

pa-*_*ims 1 c static-assert c-preprocessor

_Static_assert内置于某些 C 编译器(例如 gcc 和 clang)中,但可能并非所有 C 编译器都包含它。我想在使用该_Static_assert功能的同时尽可能保持我的代码跨平台。我认为最好的方法是测试

#ifdef _Static_assert
    _Static_assert(0, "Test");
#endif
Run Code Online (Sandbox Code Playgroud)

但这似乎行不通。它编译,但它没有检测到_Static_assert已定义。然后我想我可以测试编译器是否是 GCC,但我读到__GNUC__定义并不一定证明使用的编译器是 GCC。这也没有检测_Static_assert到我可能不知道的其他编译器。所以我的问题是,检测编译器是否支持_Static_assert预处理器的最佳方法是什么?

编辑:这是我想出的适合我的目的的解决方案。感谢下面的@KamilCuk 提供帮助我的链接。

// Check that we can use built-in _Static_assert
#if defined( __STDC_VERSION__ ) && __STDC_VERSION__ >= 201112L
    #define WE_HAVE_STATIC_ASSERT 1
#endif

#if WE_HAVE_STATIC_ASSERT
    _Static_assert(0, "Test");
#endif
Run Code Online (Sandbox Code Playgroud)

这段代码在 gcc 和 clang 上都适用于我:https : //godbolt.org/z/svaYjWj4j

最终编辑(我认为):这为我关于如何检测是否_Static_assert可用的原始问题提供了答案。它还提供了一个回退选项,可以在我测试的大多数编译器中产生相对有用的错误。

这是测试代码的链接:https : //godbolt.org/z/TYEj7Tezd

    // Check if we can use built-in _Static_assert
    #if defined( __STDC_VERSION__ ) && __STDC_VERSION__ >= 201112L
        #define MY_STATIC_ASSERT(cond, msg) _Static_assert(cond, msg)
    
    #else // We make our own
        // MY_JOIN macro trick generates a unique token
        #define MY_JOIN2(pre, post) MY_JOIN3(pre, post)
        #define MY_JOIN3(pre, post) pre ## post
    
        #if defined( __COUNTER__ ) // try to do it the smart way...
            #define MY_JOIN(pre) MY_JOIN2(pre, __COUNTER__)
            #define MY_STATIC_ASSERT(cond, msg) \
            static const char *MY_JOIN(static_assert)[(cond) * 2 - 1] = { msg }
    
        #else // we did our best... 
        //will break if static assert on same line in different file
            #define MY_JOIN(pre) MY_JOIN2(pre, __LINE__)
            #define MY_STATIC_ASSERT(cond, msg) \
            static const char *MY_JOIN(static_assert)[(cond) * 2 - 1] = { msg }
        #endif
    #endif
    
    /* - CHANGE CODE HERE TO TEST THE ASSERTIONS - */
    enum {
        A = 3,
        B = 3,
        C = B - A
    };
    /* - --------------------------------------- - */
    
    // Test to see if the enum values match our assertions
    MY_STATIC_ASSERT(B > A, "B must be greater than A");
    MY_STATIC_ASSERT(C > 0, "C must be greater than zero");
Run Code Online (Sandbox Code Playgroud)

我用来做这件事的有用信息来自以下链接:

http://jonjagger.blogspot.com/2017/07/compile-time-assertions-in-c.html

https://www.tutorialspoint.com/cprogramming/c_preprocessors.htm

/sf/answers/3079304721/

Kam*_*Cuk 5

如何测试 _Static_assert 是否已定义?

_Static_assert是 C11 的一部分。所以检查C11。

#if __STDC_VERSION__ > 201112L
Run Code Online (Sandbox Code Playgroud)

您也可以#include <assert.h>检查#ifdef static_assert.

我的第一个谷歌搜索static_assert.h github有一个很好的例子,如何处理不同的工具和编译器:https : //github.com/wc-duck/dbgtools/blob/master/include/dbgtools/static_assert.h#L68


如果您想编写 C11 兼容层并在代码中使用静态断言,例如使用此答案并回退到您自己的包装器:

// static_assert.h
#define CTASTR2(pre,post) pre ## post
#define CTASTR(pre,post) CTASTR2(pre,post)
#define STATIC_ASSERT(cond) \
    typedef struct { int static_assertion_failed : !!(cond); } \
        CTASTR(static_assertion_failed_,__COUNTER__)

#include <assert.h>
#ifndef static_assert
#define static_assert(expr, str)  STATIC_ASSERT(expr)
#endif

// somefile.c
#include <static_assert.h>
static_assert(something == something, "Uwu");
Run Code Online (Sandbox Code Playgroud)

  • 我不明白你的评论。我没有看到从“检查是否支持 _Static_assert”到“断言某些枚举值有意义”的链接。 (2认同)