我可以使用-Wextra -g
标志用gcc编译它,我没有错误。为什么编译器没有注意到我没有从非void函数返回任何东西?另外,我在32位和64位机器上运行它。它在32位,甚至印刷的苹果干长度10上运行得非常好。苹果颜色r'但它在64位机器上出现故障。 gcc在这里做什么给了我不可预测的行为,为什么它在编译时没有给我任何错误?
#include <stdlib.h>
#include <stdio.h>
struct apple
{
int stem_length;
char color;
};
struct apple* alloc_apple(const int stem_length, const char color)
{
struct apple* new_apple = (struct apple*)malloc(sizeof(struct apple));
new_apple->stem_length = stem_length;
new_apple->color = color;
}
int main(int argc, char* argv[])
{
struct apple* some_apple = alloc_apple(10, 'r');
printf("Apple stem length %d. Apple color %c\n", some_apple->stem_length,
some_apple->color);
free(some_apple);
return 0;
}
答案 0 :(得分:4)
alloc_apple
最后未return new_apple;
。如果new_apple
恰好留在寄存器中,当函数返回时(在i386上这通常是EAX
)预期返回值,这可能会巧合,但允许控制到达终点非void
返回函数的行为产生未定义的行为(可能包括意外按预期工作到causing demons to fly out of your nose的任何内容)。
我相当肯定,如果你用gcc -Wall
编译(启用所有警告),它会指出问题; return-type
是具体警告。
如果没有return
,则使用古老的返回表达式的值的编译器的函数甚至不起作用,因为最后一个表达式的计算结果为color
的值
答案 1 :(得分:3)
您正在使用-Wextra
,但这是错误的选择。
Gcc(以及大多数unix编译器)使用-Wall
选项启用大多数警告,包括您要查看的警告,-Wreturn-type
:http://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html
-Wall
这将启用有关某些用户认为有问题且易于避免(或修改以防止警告)的构造的所有警告,即使与宏结合使用也是如此。 -Wall打开以下警告标志:
...
-Wreturn-type
列表以及另外30个-W...
标记
而-Wextra
仅启用了-Wall
未启用的其他几个警告。
-Wextra
这会启用一些未被-Wall启用的额外警告标志。 ... 12个罕见的
-W...
选项列表
示例:
$ gcc t.c -Wextra
# No output
$ gcc t.c -Wall
t.c: In function ‘alloc_apple’:
t.c:15:1: warning: control reaches end of non-void function [-Wreturn-type]
}
^
所以,只需使用&#34; -Wall
&#34;得到大多数警告,-Wall -Wextra
以获得更多。有时你也可以使用set -Wall -Wextra -std=c99 -pedantic -pedantic-errors
来确保你的程序非常接近C99标准(但是系统头文件有非标准代码而且没有被捕获)。
同样使用clang
,它有更好的警告和默认设置的更好警告:
$ clang t.c
t.c:15:1: warning: control reaches end of non-void function [-Wreturn-type]
}
^
1 warning generated.
答案 2 :(得分:0)
问题是您无法从函数返回值。
这是未定义的行为。它只是“似乎工作”在32位,它崩溃在64位。如果您对为什么失败感到好奇,那么第一步就是获得堆栈跟踪。
至于“GCC为什么不告诉我?”
它可以:
http://gcc.gnu.org/onlinedocs/gcc-3.4.3/gcc/Warning-Options.html
-Wreturn型
每当使用默认为int的返回类型定义函数时发出警告。还警告任何没有的退货声明 返回类型不为void的函数的返回值。
对于C ++,即使指定了 -Wno-return-type ,没有返回类型的函数也会产生诊断消息。唯一的 例外是系统头中定义的主要和函数。
就个人而言,我几乎总是在开发过程中使用这些开关:
gcc -g -pedantic -Wall ...
答案 3 :(得分:0)
错误?什么错误?
“不从非空函数返回任何内容”从未被认为是C中的正式“错误”(即约束违规)。(顺便说一下,它也不是C ++中的“错误”)。这就是语言的定义方式。某些编译器可能会发出警告,但在一般情况下,不允许将其视为违反约束。
作为旁注,C和C ++在这方面的区别在于,在C ++中忘记返回某些东西总是未定义的行为。在C中,只有当您尝试在调用代码中使用函数的结果时,行为才是未定义的。否则,如果调用者忽略返回的值,则C将其视为完全正常的合法代码。