[英]extern variable prototype: comparison of array not equal to a null pointer is always true
提示:本站为国内最大中英文翻译问答网站,提供中英文对照查看,鼠标放在中文字句上可显示英文原文。
在清理旧程序时 GCC 返回了一个我无法理解的警告。 这是一个片段:
#include <stdio.h>
#include <stdint.h>
extern int *foo[];
int main(void) {
if (foo != NULL)
printf("Foo is not null\n");
return 0;
}
$ gcc -Wall main.c
main.c: In function 'main':
main.c:7:17: warning: the comparison will always evaluate as 'true' for the address of 'foo' will never be NULL [-Waddress]
7 | if (foo != NULL)
| ^~
main.c:4:13: note: 'foo' declared here
4 | extern int *foo[];
|
然后我尝试将原型更改为extern int **foo;
:
$ gcc -Wall main.c
/usr/bin/ld: /tmp/cciux1Df.o: warning: relocation against `foo' in read-only section `.text'
如这里所示,如果没有初始化,它们应该被认为是相同的。 为什么**foo
(理所当然地)无法编译为未定义的引用,而 GCC 使用*foo[]
成功编译?
relocation against 'foo' in read-only section '.text'
作为警告的真正含义是什么?
谢谢。
编译器试图告诉你这个语句
if (foo != NULL)
没有意义,因为数组总是占用 memory 而你声明了一个数组
extern int *foo[];
.
在 if 语句中,数组指示符foo
被隐式转换为int **
类型的指针,指向数组的第一个元素(即数组占用的范围为 memory)。 所以它不能等于NULL
。
请注意,您应该在这个或其他翻译单元的某处定义数组。 否则 linker 会发出未定义数组的错误。 因为上面数组的声明不是它的定义也不是它的暂定。
此测试可能用作弱链接的一种形式。 在某些情况下,该程序可能与数组的定义相关联,而在其他情况下,linker 是为符号分配零值(linker 符号的零值对应于 C 中数组的零地址) .
因此行为不会由 C 标准定义,但是这段旧代码可能没有被编写为符合标准的代码,并且这可能与当时使用的编译器和 linker 一起工作。
如这里所示,如果没有初始化,它们应该被认为是相同的。
这是数组参数上下文中的 C++ 问题。 您不应将其用于提及此问题。
为什么
**foo
(理所当然地)无法编译为未定义的引用,而 GCC 使用*foo[]
成功编译?
用extern int *foo[];
, foo
foo != NULL
中的 foo 被转换为它的第一个元素的地址,编译器假设它永远不会是 null,所以它将foo != NULL
优化为“true”。 因此,生成的 object 代码不包含对foo
的任何引用,因为优化将其删除。
用extern int **foo;
, foo
foo != NULL
中的 foo 需要获取存储在foo
中的值来测试它是否为 null 指针,因此生成的 object 代码尝试从foo
加载数据。 然后 linker 无法满足对foo
的引用,因此它会抱怨。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.