2016-08-22 35 views
15

下面的代码生成与MSVC的警告(2015年更新3)INT - 与/W4警告比较引用时为bool,并与MSVC 2015年

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) 

为什么?

编辑:

没有常量只是测试以及

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

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

编辑2:

在调试编译.. 。我不得不在沉默的情况下沉默C4127: conditional expression is constant^h ...

编辑3:

这里有3例反汇编:

常量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  [email protected] (01164B04h) 

常量只有

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  [email protected] (013A4B04h) 

没有常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  [email protected] (0154B04h) 

因此,似乎有awlays的if语句的跳跃,因此没有被优化,而不是警告,诊断为const的情况下(调试配置)...

+3

看起来好像检测逻辑不够普遍 –

+1

相关的[MSDN页面](https://msdn.microsoft.com/ja-jp/library/1hy2y0bk.aspx)表示编译器警告不要比较** int **和'bool'的值**。我没有MSVC,所以我无法确认它。可能会比较'const'值是个例外吗? – Ohashi

+0

@Ohashi是的 - 我刚刚没有测试const和ref,它又发出了一个警告...... – onqtam

回答

3

This与GCC发生了什么6.1以下代码:

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 

最容易的事情,这里要注意有关assemb在noref的情况下,甚至没有跳跃;这只是一个简单的return 1

同样的事情可能发生在MSVC,然后滑过警告的检测机制,而你只是没有得到一个。

编辑:

让我们看看你的组装,特别是常量只有版本:

if(a == b) 
0137BAB6 mov   eax,1 
0137BABB test  eax,eax 
0137BABD je   DOCTEST_ANON_FUNC_2+44h (0137BAD4h) 

虽然这是事实,if声明(je)是存在的,我们可以看到它实际上并不比较变量 - 这是触发警告的精确操作。它只是将1放入寄存器,然后将寄存器与自身进行比较。

+0

之间应该没有任何区别? – onqtam

+1

GCC的默认值不是优化('-O0')。所以是的。 –

+0

我编辑了我的答案 - 为3个案例添加了反汇编 - if语句始终存在 – onqtam