为什么GCC在获取void表达式的地址时开始发出警告?

Dol*_*000 10 c gcc

在几个GCC版本之前,我可以做这样的事情:

$ objcopy -I binary -O elf64-x86-64 -B i386 foo.png foo.png.o
Run Code Online (Sandbox Code Playgroud)

...在C中加入以下内容,作为SDL图像加载的示例:

extern void _binary_foo_png_start;
extern void _binary_foo_png_start;
SDL_Surface *image = IMG_Load_RW(SDL_RWFromMem(&_binary_foo_png_start, &_binary_foo_png_end));
Run Code Online (Sandbox Code Playgroud)

然后我将foo.png.o与C文件中的目标文件链接在一起,并获得一个整齐地包含的可执行文件foo.png.

这些天,我仍然可以这样做,但海湾合作委员会警告我:

foo.c:57:19: warning: taking address of expression of type ‘void’
foo.c:57:44: warning: taking address of expression of type ‘void’
Run Code Online (Sandbox Code Playgroud)

显然它仍然有效,据我所知,它确实做到了它应该做的事情.符号本身没有明确定义的类型,因此将它们声明为合适似乎是合适的void.我的意思是,当然,我也可以给他们任何其他任意类型,它仍然可以正常工作,就像我只是想要他们的地址一样,但声明它们void似乎比组成某种类型更好.

那么为什么GCC突然决定开始警告我这个呢?还有其他一些首选的方式吗?

n. *_* m. 5

似乎至少C11标准不允许这样:

6.3.2.1/1左值是一个表达式(对象类型不是void),可能指定一个对象.

如果您的表达式不是左值,则无法获取其地址.

声明的有效期

extern void _binary_foo_png_start;
Run Code Online (Sandbox Code Playgroud)

是有问题的,因为它可以说没有声明一个对象(一个对象不能有类型void).我试过的四个C编译器中有两个接受它.其中一个编译器接受&_binary_foo_png_start.提交了一个错误.

从历史的角度来看,似乎曾经是允许这种结构的意图(这可以解释为什么Gcc过去接受它)在DR 12中可以找到类似的讨论.请记住,相关定义(如左值)在C90,C99和C11中有所不同.

  • 回过头来看,我甚至注意到,你的(非常有趣的)DR 12的链接建议使用`extern const void`而不是简单的`extern void`,而GCC实际上并没有警告. (2认同)
  • @ Dolda2000-`extern const void`与gcc 4.9.3(gcc-arm-none-eabi-4_9-2015q3)完美配合,而`extern void`生成警告。 (2认同)