c - 初始化复杂结构,GCC 警告 : initialized field with side-effects overwritten

标签 c gcc c99

我正在编写一个西洋双陆棋位置评估系统,我正在尝试使用指定的初始化器、复合文字和可变参数宏来创建一个关键字参数函数,如 here 所述。 ,以及 Ben Klemens 的优秀著作 21st Century C

// from board.h
typedef struct _board_t board_t;  

// from evaluator.h (evaluator is an "interface" in a primitive object system.)
#define EVALUATOR(v) (evaluator_t*)(v)

enum { OUTPUT_WIN, OUTPUT_WINGAMMON, OUTPUT_WINBACKGAMMON,
       OUTPUT_LOSEGAMMON, OUTPUT_LOSEBACKGAMMON, N_OUTPUT };

typedef struct _evaluator_t evaluator_t;

// from composite_evaluator.h
#define N_MAX_EVALUATORS_IN_COMPOSITE 10

typedef evaluator_t * (*new_func)( void *d );

typedef struct {
    int n_eval;
    int (*classifier)( const board_t *b );
    struct {
        new_func construct;
        void *args;
    } config[N_MAX_EVALUATORS_IN_COMPOSITE];
} composite_evaluator_config_t;

// some evaluator implementations (just decl for _new)
typedef struct _overevaluator_t       overevaluator_t;
typedef struct _onesidebearoff_t      onesidebearoff_t;
typedef struct _neuralnet_evaluator_t neuralnet_evaluator_t;
overevaluator_t        *overevaluator_new       (void *args);
onesidebearoff_t       *onesidebearoff_new      (void *args);
neuralnet_evaluator_t  *neuralnet_evaluator_new (void *args);

// and a classifing function decl.
int classify_position( const board_t *b );

// Example from main program
#include <stdio.h>
int main()
{
    // This is of course coded in a variadic macro, but the macro is left out for simplicity of the example.
    composite_evaluator_config_t myeval = {
        .n_eval = 5,
        .classifier = classify_position,
        .config = {
          [0] = { .construct = (new_func)overevaluator_new },
          [1] = { .construct = (new_func)onesidebearoff_new },
          [2] = { .construct = (new_func)neuralnet_evaluator_new, .args = &((char*[]){"race.weights", "race", "race"}) },
          [3] = { .construct = (new_func)neuralnet_evaluator_new, .args = &((char*[]){"contact.weights", "contact", "contact"}) },
          [4] = { .construct = (new_func)neuralnet_evaluator_new, .args = &((char*[]){"crashed.weights", "crashed", "contact"}) },
          // The following line is added by a __VA_ARGS__, hence overriding the [3] above.
          [3] = { .construct = (new_func)neuralnet_evaluator_new, .args = &((char*[]){"td1228.weights", "contact", "contact"}) },
        }
    };

    char **args = (char**) myeval.config[3].args; 
    printf("Neural network weights read from '%s'.\n", args[0]);

    return 0;
}

我相信这是合法的 C99 (?),但是当我使用 GCC (4.9.2 20141224) 编译时,我收到以下警告:

$ gcc -Wall -Wextra -Wno-override-init -c evaltest.c
evaltest.c: In function ‘main’:
evaltest.c:63:13: warning: initialized field with side-effects overwritten
         [3] = { .construct = (new_func)neuralnet_evaluator_new, .args = &((char*[]){"td1228.weights", "contact", "contact"}) },
         ^
evaltest.c:63:13: warning: (near initialization for ‘myeval.config[3]’)

但是,当我用 clang 编译时,像这样:

clang -Wall -Wextra -Wno-initializer-overrides -c evaltest.c

我完全没有收到任何警告!然而,这两个编译器似乎都构建了预期的代码。

所以,clang 和我认为这是 OK 代码。有人可以解释为什么 GCC 向我发送此警告吗?警告有效吗?我可以以任何方式抑制它吗?还是 GCC 错误?

最佳答案

因为这里

[3] = { .construct = (new_func)neuralnet_evaluator_new, .args = &((char*[]){"td1228.weights", "contact", "contact"}) }

你初始化了 .config[3] 两次

Gcc 4.9 Doc: Designated-Init

If the same field is initialized multiple times, it has the value from the last initialization. If any such overridden initialization has side-effect, it is unspecified whether the side-effect happens or not. Currently, GCC discards them and issues a warning.

关于c - 初始化复杂结构,GCC 警告 : initialized field with side-effects overwritten,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28289828/

相关文章:

c - 是否可以将多个输入通过管道传输到一个程序中?

c - include 的路径解析

c - strtol 未检测到整数溢出

c++ - C/C99/C++/C++x/GNU C/GNU C99 中枚举的签名

c++ - 这个宏如何工作?

C 倒回来自命令输出的 FILE 指针

c - “inline __attribute__((always_inline))” 在函数中是什么意思?

linux - 在 Ubuntu-16.04 上从源代码安装 gcc-4.8.1

gcc - LLVM/Clang 是由 GCC 引导/编译的吗?

c - 32 位与 64 位环境中的 int_max