1.
求下列代码的打印结果
#include <stdio.h>
int main()
{
char a = -1;
signed char b = -1;
unsigned char c = -1;
printf("a=%d,b=%d,c=%d", a, b, c);
return 0;
}
答案速查
分析
之前讲过,char在VS中默认为signed char,则a和b的打印结果应该是一样的
存储范围:
signed char -128~127
unsigned char 0~255
由于整数在内存中以补码形式存储,-1为0-1在计算器求出的结果为补码
这里如果没有位数的限制,由于不断向高位借位,会显示无数个1
在这里,无论是signed char类型还是unsigned char类型,其本质是限制在内存中的存储位数,从低位截断1 byte(8 bit),为1111 1111,因此a,b,c存储的均为1111 1111
回忆:15.75.【C语言】表达式求值
表达式中的字符和短整型操作数在使用之前被转换为普通整型,这种转换称为整型提升
到了printf("a=%d,b=%d,c=%d", a, b, c);时,由于a,b,c均为字符类型,因此在打印(即使用)之前会被提升为普通整型
对于1111 1111
signed char:有符号-->最高位为符号位
最高位为1,按最高位提升,x86下为11111111 11111111 11111111 11111111
unsigned char:无符号-->最高位不是符号位,以0填充
x86下为00000000 00000000 00000000 11111111
%d 打印有符号整数,%u 打印无符号整数
补码转换为原码
11111111 11111111 11111111 11111111最高位为1是符号位,不参与运算
取反+1后10000000 00000000 00000000 00000001,打印结果为-1
00000000 00000000 00000000 11111111
最高位为0是符号位,为正数,正数的原码=反码=补码,打印结果为255
总结
类型的作用:1.申请内存空间时的大小 2.决定看待内存中数据的视角
2.
求下列代码的打印结果
#include <stdio.h>
int main()
{
char a = -128;
printf("a=%u", a);
return 0;
}
答案速查
分析
-128==0-128
截断后8bit的补码10000000
char在VS中默认为signed char,整型提升11111111 11111111 11111111 10000000
%u打印,正数的原码=反码=补码
为FF FF FF 80-->
3.
把第2题的 char a = -128; 改为128,求打印的结果
结果和第二题一样
0-128截断后8bit的补码还是为10000000
4.
求下列代码的打印结果
#include <stdio.h>
int main()
{
char a[1000];
int i;
for (i = 0; i < 1000; i++)
{
a[i] = -1 - i;
}
printf("%d", strlen(a));
return 0;
}
答案速查
分析
char类型的范围 -128~127
看循环时,从a[0]开始依次存储-1,-2,-3,...,-128,-129,-130,...,-1000
strlen找到/0(ASCII码为00)则停止,返回值
显然从-129开始存储会发生问题,char最多只能容纳8bit,计算机对于他们的处理采用"环绕溢出"机制
在15.75.【C语言】表达式求值文中有一张图,很好地解释了这个机制
对于有符号(signed char)类型
8bit补码截断后存储:
0:0000 0000
1:0000 0001
2:0000 0010
......
126:0111 1110
127:0111 1111//不可再进位,否则影响符号位
-1:1111 1111
-2:1111 1110
-127:1000 0001
-128:1000 0000//被规定为-128
-129:0111 1111-->其实是127的结果
相当于:-1,-2,-3,-4,..,-128,127,126,...,1,0一共255bytes
5.
#include <stdio.h>
unsigned char i = 0;
int main()
{
for (i = 0; i <= 255; i++)
{
printf("hello world\n");
}
return 0;
}
思想和第4题相同, unsigned char i = 0;(i范围0~255)定义全局变量
for循环中i<=255是恒成立的,死循环打印
6.(HARD★)
已知x86环境下是小端序存储,求下列代码的打印结果
#include <stdio.h>
int main()
{
int a[4] = { 1, 2, 3, 4 };
int* ptr1 = (int*)(&a + 1);
int* ptr2 = (int*)((int)a + 1);
printf("%x,%x", ptr1[-1], *ptr2);
return 0;
}