本文涉及到数据在内存中的存储的相关知识,请戳深度剖析数据在内存中的存储
例一(详细)
int main()
{
char a1 = -1;
signed char a2 = -1;
unsigned char a3 = -1;
printf("%d %d %d",a1,a2,a3 );
return 0;
}
所有常量,在没有后缀的情况下,默认是
int
型
-1
原码:1000 0000 0000 0000 0000 0000 0000 0001
反码:1111 1111 1111 1111 1111 1111 1111 1110
补码:1111 1111 1111 1111 1111 1111 1111 1111
由于
char
类型只有1个byte,所以发生整形截断,并将低位赋值给a
char a1=-1;// 1111 1111
signed char a2 = -1;//1111 1111
unsigned char a3 = -1;//1111 1111
而在printf
时,又是以%d(有符号整数)
的形式输出,所以发生整形提升
整形提升的原则:
①有符号数据类型:正数填充0,负数填充1
②无符号数据类型:填充0
char a1=-1;//1111 1111 1111 1111 1111 1111 1111 1111
signed char a2 = -1;//1111 1111 1111 1111 1111 1111 1111 1111
unsigned char a3 = -1;//0000 0000 0000 0000 0000 0000 1111 1111
例二
int main()
{
char a = -128;
printf("%u", a);
return 0;
}
同样的道理
-128
原码:1000 0000 0000 0000 0000 0000 1000 0000
反码:1111 1111 1111 1111 1111 1111 0111 1111
补码:1111 1111 1111 1111 1111 1111 1000 0000
整形截断:
char a = -128;//1000 0000
整形提升:
char a = -128;//1111 1111 1111 1111 1111 1111 1000 0000
%u(无符号整数)
所以直接可以输出:
例三
int main()
{
char a = 128;
printf("%u", a);
return 0;
}
128
原码:0000 0000 0000 0000 0000 0000 1000 0000
反码:0111 1111 1111 1111 1111 1111 0111 1111
补码:0111 1111 1111 1111 1111 1111 1000 0000
整形截断:
char a = 128;//1000 0000
整形提升:
char a = 128;//1111 1111 1111 1111 1111 1111 1000 0000
%u(无符号整数)
所以直接可以输出:
Tip: 虽然
char
的区间为 [-128,127],因为有截断与提升的存在所以超出区间并不影响操作
例四(涉及到运算)
int main()
{
int i= -20;
unsigned int j = 10;
printf("%d\n", i+j);
return 0;
}
-20
原码:1000 0000 0000 0000 0000 0000 0001 0100
反码:1111 1111 1111 1111 1111 1111 1110 1011
补码:1111 1111 1111 1111 1111 1111 1110 1100
10
原码/反码/补码:0000 0000 0000 0000 0000 0000 0000 1010
(-20)+10
补码相加:1111 1111 1111 1111 1111 1111 1111 0110
反码:1111 1111 1111 1111 1111 1111 1111 0101
原码:1000 0000 0000 0000 0000 0000 0000 1010
%d(有符号整数)
,所以输出结果为:
例五(有♂趣)
int main()
{
unsigned int i;
for (i = 9; i >= 0; i--)
{
printf("%u\n", i);
}
return 0;
}
%u(无符号整数)
是永远大于等于0的,所以陷入了死循环!
输出结果为(刷新很快只取局部结果):
例六(有♂趣)
int main()
{
char a[1000];
int i;
for(i=0; i<1000; i++)
{
a[i] = -1-i;
}
printf("%d",strlen(a));
return 0;
}
strlen
的用法: size_t strlen(const char *str) 计算字符串str
的长度,直到空结束字符,但不包括空结束字符
所以strlen(a)
计算a
长度只需要找出'/0'
也就是0
在哪
如图,可以得知0
在128+127+1的位置,所以输出结果为:
例七
unsigned char i = 0;
int main()
{
for(i = 0;i<=255;i++)
{
printf("hello world\n");
}
return 0;
}
与例六一样,陷入死循环!