0x00 简介
C语言中无符号整形与有符号整形,低层次与高层次类型的比较等等,涉及到默认的一些规则,
需要理解清楚。
0x01 实验
1. 无符号整形与有符号整形
unsigned int un_a = 1;
int n_b = -1;
printf("un_a<n_b: %d\n", un_a<n_b);
>> un_a<n_b: 1
有符号整形与无符号整形比较时,按无符号进行比较,所以n_b = -1 => n_b = 0xffffffff > 1
2. 无符号char与有符号char
char c_a = -1;
unsigned char uc_b = -1;
printf("c_a<uc_b: %d\n", c_a<uc_b);
>> c_a<uc_b: 1
char与unsigned char以及short与unsigned short都会先扩展为与其同符号的整形,即char->int,
unsigned char->unsigned int等等,然后再做有符号比较。
3. 有符号整形与无符号char
int n_a = 1;
unsigned char uc_b = -1;
printf("n_a<uc_b: %d\n", n_a<uc_b);
>> n_a<uc_b: 1
uc_b先做无符号扩展(movzx)为uint型0xff,然后再做有符号比较,则n_a = 1 < 0xff = (int)((uint)uc_b)
4. 无符号整形与有符号char比较
unsigned int un_a = 1;
char c_b = -1;
printf("un_a<c_b: %d\n", un_a<c_b);
>> u_a<c_b: 1
c_b先做有符号扩展(movsx)为int型0xffffffff,然后再做无符号比较,则un_a = 1 < 0xffffffff = (uint)((int)c_b)
5. 有符号整形与常量比较
int n_a = -1;
printf("n_a<80: %d\n", n_a<80);
>> n_a<80: 1
有符号整形跟常量比较时,做有符号比较
6. 无符号整形与常量比较
unsigned int un_a = -1;
printf("un_a<80: %d\n", un_a<80)
>> un_a<80: 0
无符号整形与常量比较时,做无符号比较
7. 低层次有符号类型与常量比较
char ch = 0xff;
printf("ch<80: %d\n", ch<80);
>> ch<80: 1
ch先做符号扩展(movsx)为0xffffffff,然后再做有符号比较,则(int)ch = 0xffffffff < 80
8. 低层次有符号类型与常量比较
unsigned char u_ch = 0xff;
printf("u_ch<0xffffffff: %d\n", u_ch<0xffffffff);
>> u_ch<0xffffffff: 1
u_ch先做无符号扩展(movzx)为0x000000ff,然后再做无符号比较。
9. 低层次有符号类型强制转化为高层次类型再与常量比较
char ch = 0xff;
int n_a = (int)ch;
printf("n_a<0x80: %d\n", n_a<0x80);
>> n_a<0x80: 1
ch先做符号扩展为0xffffffff,所以n_a = 0xffffffff = -1 < 0x80
10. 低层次有符号类型强制转化为高层次类型再与常量比较
char u_ch = 0xff;
int n_a = (int)u_ch;
printf("n_a<0x80: %d\n", n_a<0x80);
printf("n_a<0xffffffff: %d\n", n_a<0xffffffff)
int n_b = -1;
printf("n_a<n_b: %d\n", n_a<n_b);
>> n_a<0x80: 0
>> n_a<0xffffffff: 1
>> n_a<n_b: 0
有没有一点意外,u_ch先做无符号扩展为0x000000ff,当与常量作比较时,做无符号比较,而与变量做比较时,按实验1中规则,这个我也觉得很诡异
,还望理解清楚的说一下
,附上编译后的汇编代码:
mov byte ptr[u_ch], 0FFh
movzx eax, byte ptr [u_ch]
mov dword ptr[n_a], eax
cmp dword ptr[n_a], 0FFFFFFFFh
sbb eax, eax
neg eax
mov esi, esp
push eax
push offset string "n_a<0xffffffff: %d\n"
call _printf
11. 指针类型与指针类型比较
unsigned char *pch = (unsigned char *)-1;
unsigned char *pch2 = (unsigned char *)1;
printf("pch<pch2: %d\n", pch<pch2);
>> pch<pch2: 0
指针类型相互做比较时,做无符号比较
0x02 小结
1. 无符号类型与有符号类型(这里的类型都是不低于整形层次的类型)做比较时,按无符号进行比较;
2. 两个低层次类型(低于整形的同属于低层次)的变量进行比较时,先同符号扩展为高层次的类型,然后再做有符号比较;
3. 低层次与高层次类型做比较时,低层次的先同符号扩展为与高层次同级的类型,然后再根据高层次类型有无符号,做相应的有无符号比较。
4. 变量与常量进行比较时,做与变量本身同符号的比较,即变量本来是有符号,则做有符号比较,否则做无符号比较。
5. 低层次的变量与常量进行比较时,低层次的先同符号扩展为与高层次同级的类型,然后再做与其符号相同的比较。
6. 低层次类型强制转换为高层次类型时,先做与低层次类型同符号的扩展,然后当转换后高层次类型与常量比较时,也是做与低层次类型同符号的比较。
7. 指针类型做比较时,做无符号比较。