printf("%lld\n", -18446744073709551615);
//18446744073709551615 == 0xffffffffffffffff(16个f)
查看反汇编结果
编译选项clang -m64 -std=c99 -W -Wall
,编译结果是
warning: integer literal is too large to be represented in a
signed integer type, interpreting as unsigned
[-Wimplicitly-unsigned-literal]
printf("%lld\n", -18446744073709551615);
1 warning generated.
在web aside CS:APP Web Aside DATA:TMIN:Writing TMin in C里有一句话
When the compiler encounters a number of the form -X, it
first determines the data type and value for X and then negates it.
那么这个negate的过程是什么时候发生的,具体是怎样发生的。
例如,上面那个c语句字面量的值变成了 1
,我的理解是:
18446744073709551615
转成unsigned long(64位下我的机器的sizeof(long)==8)
。
然后取反,我猜测用0x10000000000000000(16个0)
减去18446744073709551615
实现的,也就是变成了1
.
那么就有以下问题
- 这样理解对不对,以及怎么验证。
- 有没有办法查看字面量的机器码
Assembly
0000000000400530 <main>:
400530: 55 push %rbp
400531: 48 89 e5 mov %rsp,%rbp
400534: 48 83 ec 10 sub $0x10,%rsp
400538: 48 bf e4 05 40 00 00 movabs $0x4005e4,%rdi
40053f: 00 00 00
400542: b8 01 00 00 00 mov $0x1,%eax
400547: 89 c6 mov %eax,%esi
400549: b0 00 mov $0x0,%al
40054b: e8 b0 fe ff ff callq 400400 <printf@plt>
400550: 31 c9 xor %ecx,%ecx
400552: 89 45 fc mov %eax,-0x4(%rbp)
400555: 89 c8 mov %ecx,%eax
400557: 48 83 c4 10 add $0x10,%rsp
40055b: 5d pop %rbp
40055c: c3 retq
40055d: 0f 1f 00 nopl (%rax)