其他
为什么 2 < 3 ? : 100 的结果是1?
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 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
编译脚本
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.12) 5.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.
点分享
点点赞
点在看