设计程序判断当前当前机器的字节序(即大端还是小端的存储模式) ::: tip 假设int a = 20;十六进制表示为0x00000014内存中从左向右地址由低到高,大端存储是00 00 00 14,小端存储是14 00 00 00。 可以通过比较第一个字节和变量最低位的两个数字来判断是大端存储还是小端存储。 ::: 指针的类型决定了指针进行解引用操作时能够访问的空间大小。 即可以通过解引用char类型指针取出一个字节。如果取到的是00,即为大段存储,如果取到的是14,即为小端存储。 代码思路如下:
int main()
{
int a = 1; //0x00000001
char* p = (char*)&a; //强制转换为char类型。指针*p存储地址,值不变,类型改变
if (*p == 1)
{
printf("小端");
}
else
{
printf("大端");
}
return 0;
}
完善后的代码:
int check_sys(int a)
{
char* p = &a;
if (*p == 1)
{
return 1;
}
else
{
return 0;
}
}
int main()
{
int a = 1;
int ret = check_sys(a);
if (ret == 1)
{
printf("小端");
}
else if(ret == 0)
{
printf("大端");
}
return 0;
}
判断输出内容题目1:
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;
}
a = -1,b = -1,c = 255
- a的补码是11111111111111111111111111111111,存放在char类型的a中发生截断,保留11111111,a是有符号数,符号位为1,%d输出整型,整型提升补1,11111111111111111111111111111111,输出时计算反码、原码,存放在char类型的a中发生截断,变为11111111,a是有符号数,输出-1。
- b和a相同,输出-1。
- c的补码是11111111111111111111111111111111,存放在char类型的c中发生截断,保留11111111,c是无符号数,符号位为0,%d输出整型,整型提升补0,即为00000000000000000000000011111111,存放在char类型的c中发生截断,变为11111111,c是无符号数,输出255。
判断输出内容题目2:
int main()
{
char a = -128;
printf("a = %u", a);
return 0;
}
a = 4294967168
- a的补码是11111111111111111111111110000000,截断后存在char类型的a中为10000000,按照符号位整型提升变为11111111111111111111111110000000,按照%u的形式打印时,将a当作无符号数,无符号数的原码和补码相同,原码直接打印,就是得到的值4294967168。
::: tip
在进行补码的计算时,当计算机识别到10000000时,不经过计算直接翻译为-128。
:::
如下:
如果使用9个比特位表示-128的原码,110000000,第一个1是符号位,反码为101111111,补码为110000000。去掉符号位时,-128的补码和计算机识别到的10000000一样,所以计算机将这一串二进制序列直接规定为-128。
::: tip
有符号数的char能表示的范围是从127到-128。
原码计算过补码后计算。
00000000-01111111表示0127
10000000-11111111表示-128-1
无符号数的char能表示的范围是从0到255。
8位二进制数全部是有效位。原码和补码相同可以直接计算。
00000000表示0,11111111表示255。
:::
上图的两个程序的区别是a的值。char类型中存放的变量是有符号数,最大只有127,a的128实际是127+1。127的二进制位是01111111,加上00000001后变为10000000,为-128。
int main()
{
char a = 128;
printf("a = %u", a);
return 0;
}
a = 4294967168
int main()
{
char a = -128;
printf("a = %u", a);
return 0;
}
a = 4294967168