2016-11-07 65 views
5

奇怪的行为,我对计算机科学的教学助理和我的一个学生提出以下的代码来检查一个整数是否是奇数还是偶数:检查一个数字是否在C++中是奇数。代码

int is_odd (int i) { 
    if((i % 2 == 1) && (i % 2 == -1)); 
    else; 
} 

令人惊讶的(至少对我来说)这个代码提供正确的结果。我测试了高达100000000的数字,并且我实在无法解释为什么这个代码的行为与它一样。

我们正在使用gcc V6.2.1和C++

我知道,这是不是这么一个典型的问题,但我希望能找到一些帮助。

+6

给出正确结果?该函数应该返回一个int,但不返回任何内容。它的行为是不确定的。你如何确定结果是“正确的”? – StoryTeller

+0

当你实际修复它时,它根本不正确。 http://ideone.com/5bs2aF – StoryTeller

+0

行为未定义。看看[这里](http://melpon.org/wandbox/permlink/HbRsBuRh5fAnBA0U)。我们可以构建一个关于'mod'的论据或者在'eax'中相应地留下'0'或'1'的东西,但是它很脆弱 – krzaq

回答

15

不考虑实际发生在您的编译器中的情况,在不返回任何东西的情况下流动函数的末尾是未定义的行为。请注意,如果您通过-O3GCC或使用Clang,那么您会得到不同的结果。

至于为什么你实际看到的“正确”的答案,这是x86组件,GCC 6.2会产生在-O0

push rbp 
    mov  rbp, rsp 
    mov  DWORD PTR [rbp-4], edi 
    mov  eax, DWORD PTR [rbp-4] 
    cdq 
    shr  edx, 31 
    add  eax, edx 
    and  eax, 1 
    sub  eax, edx 
    cmp  eax, 1 
    nop 
    pop  rbp 
    ret 

,如果你不能阅读的x86别担心。重要的是要注意的是,eax用于返回值,并且if语句的所有中间计算都使用eax作为其目标。所以当函数退出时,eax恰好有分支检查的结果。

当然,这纯属学术讨论;学生的代码是错误的,我肯定会给它零分,不管它是否通过了你运行的任何测试。

+2

我认为,通过改变调用约定可以进一步证明这一点的脆弱性。 – StoryTeller

+1

是的代码可能是错误的,但我仍然想知道为什么它仍然有效,因为我想了解为什么系统的行为像它一样。 (因为每一个好的计算机科学家都应该这样做)) – DonMushroom

+0

downvote的任何原因?也许我试图解释一些UB会激怒某人:D – TartanLlama

相关问题