GCC's documentation说-Wstrict-aliasing=3
是最准确的水平,较低的水平更有可能产生误报。
我认为以下示例都违反了严格的别名规则:
float violate1(float a_float)
{
float * f_data(&a_float);
int * i_data((int *)f_data);
int value(*i_data);
return value + a_float;
}
float violate2(float a_float)
{
int * i_data((int *)&a_float);
int value(*i_data);
return value + a_float;
}
float violate3(float *f_data)
{
int * i_data((int *)f_data);
int value(*i_data);
return value + *f_data;
}
然而,当使用-Wstrict-aliasing=1
时,g ++仅为它们提供警告。
-Wstrict-aliasing=3
{}未发出警告:https://godbolt.org/g/aox2S1
这些例子实际上是不是违规行为,还是GCC的警告不是违规行为的可靠迹象?
答案 0 :(得分:3)
严格别名规则以[basic.lval]
非常明确地表达如果程序试图通过以下类型之一以外的glvalue访问对象的存储值,则行为未定义:
- 对象的动态类型[...]
这意味着violate1
和violate2
是相同的,并且必然是违规行为。
一个对象指针can be casted往返于另一个任意对象指针类型,结果是原始指针。在violate3
中,如果f_data
是int*
之前投放到float*
的{{1}},则*i_data
不会发生违规行为,但会在*f_data
发生违规行为{1}}