查看原文
其他

为什么 2 < 3 ? : 100 的结果是1?

IT服务圈儿 2023-02-06

The following article is from 嵌入式Linux Author 写代码的篮球球痴

源丨经授权转自 嵌入式Linux(ID:Linux-c-world)

作者丨写代码的篮球球痴

Linux内核里面很多这样的写法

特别是这个代码

讲真,这样的代码在我们这里是会被叼的,好好的代码你不写,你非得写一个似懂非懂的意思。


err_out:
  err2 = sg_finish_rem_req(srp);
  sg_remove_request(sfp, srp);
  return err ? : err2 ? : count;



但是你有没有想过,如果等于,到底是多少呢?

我们先看下这个代码的汇编程序


#include <stdio.h>

int main()
{
  int a = 2;
  int b = 3;
  int c = a < b ? : 4;
  printf("%d\n",c);
  return 0;
}



汇编


.file  "test23.c"
  .section .rodata
.LC0:
  .string  "%d\n"
  .text
  .globl main
  .type  main, @function
main:
.LFB0:
  .cfi_startproc
  pushq %rbp
  .cfi_def_cfa_offset 16
  .cfi_offset 6, -16
  movq %rsp, %rbp
  .cfi_def_cfa_register 6
  subq $16, %rsp
  movl $2, -12(%rbp)
  movl $3, -8(%rbp)
  movl -12(%rbp), %eax
  cmpl -8(%rbp), %eax
  setl  %al
  movzbl %al, %eax
  andl $1, %eax
  testb %al, %al
  je .L2
  movl -12(%rbp), %eax
  cmpl -8(%rbp), %eax
  setl  %al
  movzbl %al, %eax
  jmp .L3
.L2:
  movl $4, %eax
.L3:
  movl %eax, -4(%rbp)
  movl -4(%rbp), %eax
  movl %eax, %esi
  movl $.LC0, %edi
  movl $0, %eax
  call  printf
  movl $0, %eax
  leave
  .cfi_def_cfa 78
  ret
  .cfi_endproc
.LFE0:
  .size main, .-main
  .ident "GCC: (Ubuntu 5.4.0-6ubuntu1~16.04.12) 5.4.0 20160609"
  .section .note.GNU-stack,"",@progbits



编译脚本


gcc -E test23.c -o test23.i
gcc -S test23.i
gcc -S test23.i -o test23.s
gcc -c test23.s -o test23.o
gcc test23.o -o test23.out
chmod 777 test23.out
./test23.out



代码输出


qqqq@ubuntu:/study$ ./test23.sh
1
qqqq@ubuntu:/study$



给关键的汇编代码加上注释


.file "test23.c"
  .section .rodata
.LC0:
  .string "%d\n"
  .text
  .globl main
  .type  main, @function
main:
.LFB0:
  .cfi_startproc
  pushq %rbp
  .cfi_def_cfa_offset 16
  .cfi_offset 6, -16
  movq %rsp, %rbp
  .cfi_def_cfa_register 6
  subq $16, %rsp
  movl $2, -12(%rbp) #给a 赋值2
  movl $3, -8(%rbp) #给b 赋值3
  movl -12(%rbp), %eax #给a 填充到 eax 寄存器
  cmpl -8(%rbp), %eax # 比较 b 和 a 的大小
  setl %al # 因为 a 小于 b 所以 al 置1
  movzbl %al, %eax # al 填充到 eal
        # 详解看这个 https://www.cnblogs.com/johnnyflute/p/3597352.html
  andl $1, %eax #按位与
  testb %al, %al #判断al 是否等于0,如果等于0,就跳转到 L2
  je .L2
  movl -12(%rbp), %eax
  cmpl -8(%rbp), %eax
  setl %al
  movzbl %al, %eax
  jmp .L3
.L2:
  movl $4, %eax # 输出4
.L3:
  movl %eax, -4(%rbp)
  movl -4(%rbp), %eax
  movl %eax, %esi
  movl $.LC0, %edi
  movl $0, %eax
  call printf
  movl $0, %eax
  leave
  .cfi_def_cfa 7, 8
  ret
  .cfi_endproc
.LFE0:
  .size main, .-main
  .ident "GCC: (Ubuntu 5.4.0-6ubuntu1~16.04.12) 5.4.0 20160609"
  .section .note.GNU-stack,"",@progbits



我们稍微修改下代码,然后再看看汇编


#include <stdio.h>

int main()
{
  int a = 4;
  int b = 3;
  int c = a < b ? : 4;
  printf("%d\n",c);
  return 0;
}


代码输出

qqqq@ubuntu:/study$ ./test23.sh
4
qqqq@ubuntu:/study$



通过比较发现汇编代码,只有一行不一样



关键的差异,就是在比较代码的位置,以比较结果看是否执行 setl %al

这也是为什么下面的代码结果是1的原因

我使用的GCC版本是


gcc (Ubuntu 5.4.0-6ubuntu1~16.04.125.4.0 20160609
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.


1、2022年CSS都有哪些更新?

2、如果我有罪,请让法律制裁我,而不是用 AI 面试折磨我

3、刺激,线程池的一个BUG直接把CPU干到100%了。

4、“投屏”风波后,爱奇艺上线远程为父母付款功能

5、多线程引发的惨案直接把年终给干没了

点分享

点点赞

点在看

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存