我编写了一个步步高位置评估系统,我尝试使用指定的初始化器,复合文字和可变参数宏来创建关键字参数函数,如描述here,并在Ben Klemens& #39;优秀的书 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和我认为这是好的代码。有人可以解释为什么GCC发给我这个警告吗?警告有效吗?我能以任何方式压制它吗?或者它是GCC的错误?
答案 0 :(得分:1)
因为这里
[3] = { .construct = (new_func)neuralnet_evaluator_new, .args = &((char*[]){"td1228.weights", "contact", "contact"}) }
你已经.config[3]
两次
如果多次初始化相同的字段,则它具有上次初始化的值。如果任何此类重写的初始化具有副作用,则未指定副作用是否发生。目前,GCC丢弃它们并发出警告。