首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在C语言中,为什么短路优先于增量?

在C语言中,为什么短路优先于增量?
EN

Stack Overflow用户
提问于 2014-04-29 14:42:15
回答 2查看 74关注 0票数 0
代码语言:javascript
复制
void main()
{
  int i=-3, j=2, k=0,m;
  m = ++i && ++j || ++k;
  printf("\n%d %d %d %d",i,j,k,m);
}

此代码段打印-2 3 0 1,但为什么不打印-2 3- 1 1。即使k的++运算符优先于逻辑运算符,为什么k不会因为短路而递增?更普遍的是,当涉及到逻辑运算符和副作用时,如何应用优先?

EN

回答 2

Stack Overflow用户

发布于 2014-04-29 15:10:11

这里的短路表示,如果逻辑AND运算符&&的左操作数计算结果为false,则它不会计算其右操作数。同样,如果逻辑OR运算符||的左操作数的计算结果为true,则不计算其右操作数。这是因为,无论正确的操作数的计算结果如何,结果都不会受到影响。

此外,与||算子相比,&&具有更高的优先级。

因此,表达式m = ++i && ++j || ++k;等同于

代码语言:javascript
复制
m = (++i) && (++j || ++k);

左操作数++i的计算结果为-2,它是true (非零)。因此,现在计算第二个表达式(++j || ++k)||运算符的左操作数是++j,其计算结果为3,即true。这意味着不计算表达式++k||的右操作数。

因此,仅计算子表达式++i++j。当表达式为true时,整个表达式的计算结果为1

票数 1
EN

Stack Overflow用户

发布于 2014-04-29 15:10:13

首先,主函数(除非你使用古老的Turbo )应该返回int

其次,一个不错的编译器(对我来说是clang)抱怨这个可疑的表达式:

代码语言:javascript
复制
clang++ -S -mllvm --x86-asm-syntax=intel ls.cpp 
ls.cpp:5:11: warning: '&&' within '||' [-Wlogical-op-parentheses]
  m = ++i && ++j || ++k;
      ~~~~^~~~~~ ~~
ls.cpp:5:11: note: place parentheses around the '&&' expression to silence this warning
  m = ++i && ++j || ++k;
          ^
      (         )
1 warning generated.

第三,让我们看看程序集的输出:

代码语言:javascript
复制
    mov dword ptr [rbp - 8], -3       # this is i
    mov dword ptr [rbp - 12], 2       # this is j
    mov dword ptr [rbp - 16], 0       # this is k

    mov eax, dword ptr [rbp - 8]      # this is i++
    add eax, 1
    mov dword ptr [rbp - 8], eax
    cmp eax, 0                        # is i++ == 0?
    je  .LBB0_2
# BB#1:                               # no, i++ is NOT 0
    mov al, 1
    mov ecx, dword ptr [rbp - 12]     # this is j++
    add ecx, 1
    mov dword ptr [rbp - 12], ecx     
    cmp ecx, 0
    mov byte ptr [rbp - 21], al       # store al as a flag somewhere else
                                      # it will be the final result of the operation
    jne .LBB0_3                       # if j++ was NOT zero, go down to LBB0_3


.LBB0_2:                             # Yes, i++ is 0. Did you remark that
                                         # it didn't increment j in this case?
                                         # but it needs to increment k since the first
                                         # part of the OR evaluated to false.
    mov eax, dword ptr [rbp - 16]    # This is k++
    add eax, 1
    mov dword ptr [rbp - 16], eax
    cmp eax, 0                       # is c++ 0?
    setne   cl                       # if yes, set cl as a flag to 1
    mov byte ptr [rbp - 21], cl # 1-byte Spill

    # and here we get if j++ was not zero, 
    # so did you remark that k was not incremented?
.LBB0_3:
    mov al, byte ptr [rbp - 21] # 1-byte Reload
    lea rdi, qword ptr [.L.str]
    and al, 1
    movzx   ecx, al
    mov dword ptr [rbp - 20], ecx

    # there goes the printf    
    mov esi, dword ptr [rbp - 8]
    mov edx, dword ptr [rbp - 12]
    mov ecx, dword ptr [rbp - 16]
    mov r8d, dword ptr [rbp - 20]
    mov al, 0
    call    printf
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23357337

复制
相关文章

相似问题

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