首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >这个C函数应该总是返回false,但它没有

这个C函数应该总是返回false,但它没有
EN

Stack Overflow用户
提问于 2016-04-07 20:27:08
回答 2查看 20.1K关注 0票数 323

很久以前,我在一个论坛上偶然发现了一个有趣的问题,我想知道答案。

考虑下面的C函数:

f1.c

代码语言:javascript
复制
#include <stdbool.h>

bool f1()
{
    int var1 = 1000;
    int var2 = 2000;
    int var3 = var1 + var2;
    return (var3 == 0) ? true : false;
}

var3 == 3000开始,这应该总是返回falsemain函数如下所示:

main.c

代码语言:javascript
复制
#include <stdio.h>
#include <stdbool.h>

int main()
{
    printf( f1() == true ? "true\n" : "false\n");
    if( f1() )
    {
        printf("executed\n");
    }
    return 0;
}

因为f1()应该总是返回false,所以可以预期程序只会在屏幕上打印一个false。但编译运行后,也会显示executed:

代码语言:javascript
复制
$ gcc main.c f1.c -o test
$ ./test
false
executed

为什么会这样呢?这段代码是否有某种未定义的行为?

注意:我是用gcc (Ubuntu 4.9.2-10ubuntu13) 4.9.2编译的。

EN

回答 2

Stack Overflow用户

发布于 2016-04-09 17:24:10

我认为Lundin的优秀答案中提到的大小不匹配实际上发生在哪里,这是很有趣的。

如果使用--save-temps进行编译,您将获得可以查看的程序集文件。下面是f1()执行== 0比较并返回其值的部分:

代码语言:javascript
复制
cmpl    $0, -4(%rbp)
sete    %al

返回的部分是sete %al。在C的x86调用约定中,通过寄存器%eax返回小于或等于4个字节的返回值(包括intbool)。%al%eax的最低字节。因此,%eax的高3个字节处于不受控制的状态。

现在在main()

代码语言:javascript
复制
call    f1
testl   %eax, %eax
je  .L2

这将检查整个%eax是否为零,因为它认为它正在测试一个int。

添加显式函数声明会将main()更改为:

代码语言:javascript
复制
call    f1
testb   %al, %al
je  .L2

这就是我们想要的。

票数 38
EN

Stack Overflow用户

发布于 2016-04-07 20:37:06

请使用如下命令进行编译:

代码语言:javascript
复制
gcc -Wall -Wextra -Werror -std=gnu99 -o main.exe main.c

输出:

代码语言:javascript
复制
main.c: In function 'main':
main.c:14:5: error: implicit declaration of function 'f1' [-Werror=impl
icit-function-declaration]
     printf( f1() == true ? "true\n" : "false\n");
     ^
cc1.exe: all warnings being treated as errors

有了这样的消息,您应该知道如何纠正它。

编辑:在阅读了一条(现已删除的)注释后,我尝试在不使用标志的情况下编译您的代码。好吧,这导致了链接器错误,没有编译器警告,而不是编译器错误。而且这些链接器错误更难理解,所以即使-std-gnu99不是必需的,请始终尝试至少使用-Wall -Werror,这将为您省去很多麻烦。

票数 27
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/36476178

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档