如何禁用此特定警告

时间:2016-09-15 12:51:55

标签: c gcc warnings

这个简单的代码:

#define WIDTH 500.5
#define NB 23.2

int x[(int)(WIDTH/NB)];

给了我一个警告:

prog.c:4:1: warning: variably modified 'x' at file scope [enabled by default]

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

传递WIDTH宏的浮点值会强制评估编译器,从而发出警告,因为数组的大小不是一样的。

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

我想找到一种方法

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

3 个答案:

答案 0 :(得分:4)

它违反了标准:

  

整数常量表达式

     

整数常量表达式是   只包含赋值之外的运算符的表达式,   增量,减量,函数调用或逗号,但强制转换除外   运算符只能将算术类型转换为整数类型,整数   常量,枚举常量,字符常量,浮动   常量,但仅当它们立即用作强制转换的操作数时   到整数类型

进一步说:

  

以下上下文要求表达式称为整数   常数表达式':

     

...

     
      
  • 数组指示符中的索引(自C99起)
  •   

答案 1 :(得分: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

这在 gcc 和 clang 模式下编译时没有警告,在 C++ 模式下有 old-style cast to 'int' 警告。

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

/* ================= 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)];

在 C 和 C++ 模式下,在 gcc 和 clang 中编译时没有警告。

只有在 gcc 接受 _Pragma("GCC diagnostic ....") pragma 的地方才需要带有 int 虚拟成员的结构体。

Example


Extended implementation 适用于 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)];

答案 2 :(得分:-1)

以下GNU GCC中的一个示例可以帮助您:

  #pragma GCC diagnostic error "-Wuninitialized"
    foo(a);                       /* error is given for this one */
  #pragma GCC diagnostic push
  #pragma GCC diagnostic ignored "-Wuninitialized"
    foo(b);                       /* no diagnostic for this one */
  #pragma GCC diagnostic pop
    foo(c);                       /* error is given for this one */
  #pragma GCC diagnostic pop
    foo(d);                       /* depends on command-line options */