如何禁用此特定警告

Jea*_*bre 5 c gcc warnings

这个简单的代码:

#define WIDTH 500.5
#define NB 23.2

int x[(int)(WIDTH/NB)];
Run Code Online (Sandbox Code Playgroud)

给我一个警告:

prog.c:4:1: warning: variably modified 'x' at file scope [enabled by default]
Run Code Online (Sandbox Code Playgroud)

如果我设置#define WIDTH 500#define NB 23,警告消失.

WIDTH编译器传递宏强制评估浮点值,从而发出警告,因为数组没有常量大小.

预处理的C代码看起来像int x[(int)(500.5/23.2)];,但int x[(int)(500/23)];对于编译器是可以的(值已经是常量整数)

我也希望找到一种方法

有趣的事情:编译g++我没有警告,而我在这里读到可变长度数组在C++中没有正式支持,仅在C99中.但这对我来说不是一个选择,因为我需要坚持C.

T S*_*T S 1

可以确保像这样创建一个普通数组(非 VLA):

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpedantic"
enum{ARRAY_DIMENSION_OF_x = (int)(WIDTH/NB)};
int x[ARRAY_DIMENSION_OF_x];
#pragma GCC diagnostic pop
Run Code Online (Sandbox Code Playgroud)

在 gcc 和 clang 的 C 模式下编译时不会发出警告,old-style cast to 'int'在 C++ 模式下会发出警告。

还可以在宏中隐藏枚举的创建:

/* ================= define MAKE_CONST_INT() macro ================= */
#ifdef __cplusplus
     template<class T> struct make_const_int_helper{static T t;};
#    define MAKE_CONST_INT(x) (sizeof(*(make_const_int_helper<char (*)[int((x)+0L)]>::t)))  /* +0L avoids "useless cast" warning*/
#else
#    define EVALUATE_TO_0(type) (0*__builtin_types_compatible_p(type,int))
#    define EVALUATE_TO_0_PRAGMA(x) EVALUATE_TO_0(struct{int dummy; _Pragma(x)})

#    define EVALUATE_TO_0_START_DISABLE_WARNINGS                                \
        ( EVALUATE_TO_0_PRAGMA("GCC diagnostic push")                           \
        + EVALUATE_TO_0_PRAGMA("GCC diagnostic ignored \"-Wpedantic\"")         \
        + EVALUATE_TO_0_PRAGMA("GCC diagnostic ignored \"-Wc++-compat\"") )
#    define EVALUATE_TO_0_END_DISABLE_WARNINGS \
        EVALUATE_TO_0_PRAGMA("GCC diagnostic pop")

#    define MAKE_CONST_INT(x) MAKE_CONST_INT_HELPER2(x,__LINE__,__COUNTER__)
#    define MAKE_CONST_INT_HELPER2(x,line,counter) MAKE_CONST_INT_HELPER(x,line,counter)
#    define MAKE_CONST_INT_HELPER(x,line,counter)                                   \
        ( EVALUATE_TO_0_START_DISABLE_WARNINGS                                      \
        + EVALUATE_TO_0(enum{ INT_CONSTANT_##counter##_AT_LINE_##line = (int)(x) }) \
        + INT_CONSTANT_##counter##_AT_LINE_##line                                   \
        + EVALUATE_TO_0_END_DISABLE_WARNINGS)
#endif





/* ================= test MAKE_CONST_INT() macro ================= */
#define WIDTH 500.5
#define NB 23.2
extern int x[MAKE_CONST_INT(WIDTH/NB)];
Run Code Online (Sandbox Code Playgroud)

这在 gcc 和 Clang 以及 C++ 模式下编译时不会发出警告。

具有 int 虚拟成员的结构仅需要获得 gcc 接受编译指示的位置_Pragma("GCC diagnostic ....")

例子


适用于 MSVC、gcc、clang 和 icc的扩展实现,但仍然无法在非常挑剔的编译器上进行编译:

/* ================= define MAKE_CONST_INT() macro ================= */
#ifdef __cplusplus
#    if defined(__GNUC__) && !defined(__clang__)
 #       pragma GCC diagnostic push
 #       pragma GCC diagnostic ignored "-Wtemplates"
#    endif
    template<class T> struct make_const_int_helper{static T t;};
#    if defined(__GNUC__) && !defined(__clang__)
 #       pragma GCC diagnostic pop
#    endif
#    define MAKE_CONST_INT(x) (sizeof(*(make_const_int_helper<char (*)[int((x)+0L)]>::t)))  /* +0L avoids "useless cast" warning*/
#else
#    if defined(__GNUC__)
#        define EVALUATE_TO_0(type) (0*__builtin_types_compatible_p(type,int))
#        define EVALUATE_TO_0_PRAGMA(x) EVALUATE_TO_0(struct{int dummy; _Pragma(x)})
#        define EVALUATE_TO_0_START_DISABLE_WARNINGS                                \
            ( EVALUATE_TO_0_PRAGMA("GCC diagnostic push")                           \
            + EVALUATE_TO_0_PRAGMA("GCC diagnostic ignored \"-Wpedantic\"")         \
            + EVALUATE_TO_0_PRAGMA("GCC diagnostic ignored \"-Wc++-compat\"") )
#        define EVALUATE_TO_0_END_DISABLE_WARNINGS \
            EVALUATE_TO_0_PRAGMA("GCC diagnostic pop")                       
#    else
#        define EVALUATE_TO_0(type) (0*sizeof(type))
#        if defined(_MSC_VER)
#            define EVALUATE_TO_0_START_DISABLE_WARNINGS \
                (0 __pragma(warning( push )) __pragma(warning(disable:4116)))
#            define EVALUATE_TO_0_END_DISABLE_WARNINGS (0 __pragma(warning( pop )) )
#        else
#            define EVALUATE_TO_0_START_DISABLE_WARNINGS 0  /*other compilers will not disable warning*/
#            define EVALUATE_TO_0_END_DISABLE_WARNINGS 0
#        endif
#    endif
#    define MAKE_CONST_INT(x) MAKE_CONST_INT_HELPER2(x,__LINE__,__COUNTER__)
#    define MAKE_CONST_INT_HELPER2(x,line,counter) MAKE_CONST_INT_HELPER(x,line,counter)
#    define MAKE_CONST_INT_HELPER(x,line,counter)                                   \
        ( EVALUATE_TO_0_START_DISABLE_WARNINGS                                      \
        + EVALUATE_TO_0(enum{ INT_CONSTANT_##counter##_AT_LINE_##line = (int)(x) }) \
        + INT_CONSTANT_##counter##_AT_LINE_##line                                   \
        + EVALUATE_TO_0_END_DISABLE_WARNINGS)
#endif



/* ================= test MAKE_CONST_INT() macro ================= */
#define WIDTH 500.5
#define NB 23.2
extern int x[MAKE_CONST_INT(WIDTH/NB)];
Run Code Online (Sandbox Code Playgroud)