将bool和int的引用与MSVC 2015进行比较时发出警告

时间:2016-08-22 08:59:20

标签: c++ visual-c++ compiler-warnings

以下代码使用MSVC(2015 Update 3)生成警告 - 使用/W4

const bool& a = true;
const int& b = 1;
if(a == b)

C4805: '==': unsafe mix of type 'const bool' and type 'const int' in operation

但如果没有参考文献,它会干净利落地编译。

const bool a = true;
const int b = 1;
if(a == b)

为什么?

修改

刚刚测试没有const

bool a = true;
int b = 1;
if(a == b)

警告再次出现......

编辑2:

在Debug中进行编译...虽然我确实需要在const noref情况下使C4127: conditional expression is constant静音...

编辑3:

以下是3种情况的反汇编:

const ref

0113BA92  in          al,dx  
0113BA93  sub         esp,24h  
0113BA96  mov         eax,0CCCCCCCCh  
0113BA9B  mov         dword ptr [ebp-24h],eax  
0113BA9E  mov         dword ptr [ebp-20h],eax  
0113BAA1  mov         dword ptr [ebp-1Ch],eax  
0113BAA4  mov         dword ptr [ebp-18h],eax  
0113BAA7  mov         dword ptr [b],eax  
0113BAAA  mov         dword ptr [ebp-10h],eax  
0113BAAD  mov         dword ptr [ebp-0Ch],eax  
0113BAB0  mov         dword ptr [ebp-8],eax  
0113BAB3  mov         dword ptr [a],eax  
    const bool& a = true;
0113BAB6  mov         byte ptr [ebp-9],1  
0113BABA  lea         eax,[ebp-9]  
0113BABD  mov         dword ptr [a],eax  
    const int& b = 1;
0113BAC0  mov         dword ptr [ebp-1Ch],1  
0113BAC7  lea         ecx,[ebp-1Ch]  
0113BACA  mov         dword ptr [b],ecx  
    if(a == b)
0113BACD  mov         edx,dword ptr [a]  
0113BAD0  movzx       eax,byte ptr [edx]  
0113BAD3  mov         ecx,dword ptr [b]  
0113BAD6  cmp         eax,dword ptr [ecx]  
0113BAD8  jne         DOCTEST_ANON_FUNC_2+5Fh (0113BAEFh)  
        throw 5;
0113BADA  mov         dword ptr [ebp-24h],5  
0113BAE1  push        offset __TI1H (0117318Ch)  
0113BAE6  lea         edx,[ebp-24h]  
0113BAE9  push        edx  
0113BAEA  call        __CxxThrowException@8 (01164B04h)  

仅限const

0137BA92  in          al,dx  
0137BA93  sub         esp,0Ch  
0137BA96  mov         dword ptr [ebp-0Ch],0CCCCCCCCh  
0137BA9D  mov         dword ptr [b],0CCCCCCCCh  
0137BAA4  mov         dword ptr [ebp-4],0CCCCCCCCh  
    const bool a = true;
0137BAAB  mov         byte ptr [a],1  
    const int b = 1;
0137BAAF  mov         dword ptr [b],1  
    if(a == b)
0137BAB6  mov         eax,1  
0137BABB  test        eax,eax  
0137BABD  je          DOCTEST_ANON_FUNC_2+44h (0137BAD4h)  
        throw 5;
0137BABF  mov         dword ptr [ebp-0Ch],5  
0137BAC6  push        offset __TI1H (013B318Ch)  
0137BACB  lea         ecx,[ebp-0Ch]  
0137BACE  push        ecx  
0137BACF  call        __CxxThrowException@8 (013A4B04h)  

no const no ref

0012BA92  in          al,dx  
0012BA93  sub         esp,0Ch  
0012BA96  mov         dword ptr [ebp-0Ch],0CCCCCCCCh  
0012BA9D  mov         dword ptr [b],0CCCCCCCCh  
0012BAA4  mov         dword ptr [ebp-4],0CCCCCCCCh  
    bool a = true;
0012BAAB  mov         byte ptr [a],1  
    int b = 1;
0012BAAF  mov         dword ptr [b],1  
    if(a == b)
0012BAB6  movzx       eax,byte ptr [a]  
0012BABA  cmp         eax,dword ptr [b]  
0012BABD  jne         DOCTEST_ANON_FUNC_2+44h (012BAD4h)  
        throw 5;
0012BABF  mov         dword ptr [ebp-0Ch],5  
0012BAC6  push        offset __TI1H (016318Ch)  
0012BACB  lea         ecx,[ebp-0Ch]  
0012BACE  push        ecx  
0012BACF  call        __CxxThrowException@8 (0154B04h)  

所以看起来if语句有一个跳转,所以它没有被优化,并且在const情况下没有警告诊断(debug config)......

1 个答案:

答案 0 :(得分:3)

对于以下代码,

This是GCC 6.1所发生的:

update

装配输出:

int ref(int num) {
   const bool& a = true;
   const int& b = 1;
   return a == b;
}

int noref(int num) {
   const bool a = true;
   const int b = 1;
   return a == b;
}


int noref_noconst(int num) {
   bool a = true;
   int b = 1;
   return a == b;
}

关于装配的最简单的注意事项是,ref(int): pushq %rbp movq %rsp, %rbp movl %edi, -36(%rbp) movl $1, %eax movb %al, -21(%rbp) leaq -21(%rbp), %rax movq %rax, -8(%rbp) movl $1, %eax movl %eax, -20(%rbp) leaq -20(%rbp), %rax movq %rax, -16(%rbp) movq -8(%rbp), %rax movzbl (%rax), %eax movzbl %al, %edx movq -16(%rbp), %rax movl (%rax), %eax cmpl %eax, %edx sete %al movzbl %al, %eax popq %rbp ret noref(int): pushq %rbp movq %rsp, %rbp movl %edi, -20(%rbp) movb $1, -1(%rbp) movl $1, -8(%rbp) movl $1, %eax popq %rbp ret noref_noconst(int): pushq %rbp movq %rsp, %rbp movl %edi, -20(%rbp) movb $1, -1(%rbp) movl $1, -8(%rbp) movzbl -1(%rbp), %eax cmpl -8(%rbp), %eax sete %al movzbl %al, %eax popq %rbp ret 的情况下,甚至没有跳跃;它只是一个简单的noref

同样的事情可能发生在MSVC中,然后它会越过检测机制发出警告,而你却得不到警告。

修改

让我们看一下你的程序集,特别是 const only 版本:

return 1

虽然 if(a == b) 0137BAB6 mov eax,1 0137BABB test eax,eax 0137BABD je DOCTEST_ANON_FUNC_2+44h (0137BAD4h) 语句(if)确实存在,但我们可以看到它实际上没有比较变量 - 这是触发警告的精确操作。它只是将1放入寄存器中,然后将寄存器与自身进行比较。