整型提升
C的整型算术运算符总是至少以缺省整型类型的精度来进行的。为了获得这个精度,表达式中的字符型操作数在使用之前被转化为普通整型,这种转换称为整型提升(integral Promotion)。(C和指针)
如果原始类型(char/short)的所有值都可用int类型表示,则其值将被转换为int类型;否则将被转换为unsigned int类型。
eg.
1.移位运算
#include <stdio.h>
int main()
{
unsigned char a = 0x8A;
printf("0x%x", a << 3); //0x450
}
无符号 a = 1000 1010(2);
进行算术运算 -> 移位运算 -> 提升为int型
整型 a = 0000 0000 0000 0000 0000 0000 1000 1010 (B)
移位: a = 0000 0000 0000 0000 0000 0100 0101 0000 (B) = 0x450(H)
误区:
将左移的1舍弃得到错误值0x50,实际是被提升为整型而被保留。
2.类型转化
#include <stdio.h>
int main()
{
unsigned char p = 0xff;
char q = 0xff;
if(p == q) {
printf("True.\n");
} else {
printf("False.\n"); //False
}
printf("%d %d\n", p, q); //255 -1
printf("0x%x 0x%x\n", p, q); //0xff 0xffffffff
return 0;
}
有符号转化为无符号的高位补齐:
原码:次高位补0;
补码:最高位为0,则补齐0,反之最高位为1,则补齐1;
q为正值,原反补码相同1111 1111(B)
补齐为1111 1111 1111 1111 1111 1111 1111 1111(B) -> 0xffffffff(H)
若p = 0x7f,q = 0x7f 则输出为True(q高位补齐0)。
3.strlen
#include <stdio.h>
int main()
{
int i = -1;
char str[20] = "hello world!";
if(strlen(str) > i) {
printf("%s\n", str);
} else {
printf("NUll.\n"); //NULL.
}
}
size_t strlen(const char *string); -> size_t 为unsigned int类型
所以-1被提升为无符号整型。
K&R C上这样解释,将任何整数转换为某种指定的无符号数类型数的方法是:以该无符号数类型能够表示的最大值加1为摸,找出与此整数同余的最小的非负值。听着很拗口,其实说白了,只要知道原整数的二进制表达方法,再用要即将转换的类型去解析,就得到升级后的值了。 比如-1,负数在计算机里用补码表示,0xffffffff,那升级成无符号型之后,值就是0xffffffff
4.sizeof
#include <stdio.h>
int main()
{
char a = 'A', b;
printf("%d\n", sizeof('A')); //4
printf("%d\n", sizeof(a)); //1
printf("%d\n", sizeof(a + a)); //4
printf("%d\n", sizeof('A' + 'A')); //4
printf("%d\n", sizeof(b = a + a)); //1
}
b = a + a,在进行加法运算时被提升,在赋值时,被隐式转化。
整型提升还涉及汇编方面,没有去深入去理解,下面备注个链接
博客链接