[C] 内存中类型的存储典例详解

小引

我们前面学习了数据在内存中的存储,包括整型,浮点数等等数据类型。
这里我们简单举几个例子,通过这些典例的讲解,希望可以对内存有一个更客观、更深刻的理解。


典例 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;
}
  • %d为有符号的十进制的整数,虽然a变量是一个字符类型,但是是按照十进制格式打印,所以依然输出-1。
  • signed char当前来看和char是等效的,所以前两个输出结果是一样的。
  • 无符号的char型变量c按照有符号的int型格式打印,相当于强制类型转换。十六进制0xff,理解为有符号就是-1,理解为无符号就是255
    数据在内存中具有一定的存储形式,但是存储同样的内容,可以按照不同的方式来理解

所以输出:-1 -1 255


典例 2:

#include <stdio.h>
int main()
{
    char a = -128;
    printf("%u\n",a);
    return 0;
}

char类型变量a打印为无符号整型大致过程就是:
char类型先整型提升int类型,-128的二进制之前补了很多符号位1,再变成无符号类型,结果变成了一个很大的正数。

  • char类型表示的范围是-128 ~ 127-128的表示最低一个字节1000 0000,前面的字节都是用符号位1补充的。用无符号的方式打印,结果就变成了一个很大的数,接近了一个整数能表示的最大范围了。

所以输出:4294967168


典例 3:

#include <stdio.h>
int main()
{
    char a = 128;
    printf("%u\n",a);
    return 0;
}
  • char类型最大表示到1271270111 1111,加上一变成了1000 0000,所以将128赋予char没有足够的空间存储,超过表示范围,越界行为。
  • 128的二进制表示为1000 0000,和-128相同,所以对于char类型变量,正负在内存中的表示方式一样,所以打印出来和上题相同。
    如果两个数据在内存中存储的形式是相同的,再按照相同的方式来理解,结果也肯定是相同的

所以输出:4294967168


典例 4:

int i= -20;
unsigned  int  j = 10;
printf("%d\n", i+j); 
//按照补码的形式进行运算,最后格式化成为有符号整数
  • 两个变量相加,但是类型不同,所以发生了隐式类型转换unsigned类型要比int类型精度高,所以二者都是无符号类型,用无符号表示以补码形式存储的负数,所以二者的和应该是一个很大的数。
  • -20ff ff ff ec
    1000 00 00 0a
    二者按照二进制相加为ff ff ff f6,理解为有符号为-10
    打印方式是有符号的int类型,所以这个类型转换没有实际必要,一切以打印方式为主。

所以输出:-10


典例 5:

unsigned int i;
for(i = 9; i >= 0; i--)
{
    printf("%u\n",i);
}
  • 无符号类型的变量是恒 > 0的,所以循环条件i >= 0就恒成立,无法跳出循环,出现死循环,这是一个很经典的错误
  • 变量i已经是0时,再对它进行--,相当于+= -1
    00 00 00 00 + ff ff ff ff = 理解为有符号为-1,无符号为42亿9千万,所以两个无符号相减,如果被减数小于减数就会变成负数,理解为无符号就是一个很大的数。

所以结果是:死循环


典例 6:

int main()
{
    char a[1000];
    int i;
    for(i=0; i<1000; i++)
    {
        a[i] = -1-i;
    }
    printf("%lu",strlen(a));
    return 0;
}
  • a[]不可以视为字符串,因为没有初始化不知道\0在哪里会出现。
  • strlen返回的是长度,不存在负数,所以使用无符号长整型来打印。如果要对变量a进行strlen,就说明a要是一个字符串,而a[]字符数组不是字符串。
  • 内层循环的结果:
    -1 :<ff ff ff ff>
    -2 :<ff ff ff fe>
    -3 :<ff ff ff fd>
    … …
    当结果是-256:<ff ff ff 00>时
    char类型只保留一个字节,此时a[i]的值为0,也就是ASCII码表上0号的\0,这个就是字符数组中那个结尾标志,它和之前的字符形成了一个字符串,此时i的值为 255,不会出现循环1000次及未定义行为的情况。
    当下标是255时出现\0,说明 0 ~ 254是有效位数,总共255个字符。

所以结果是:255


典例 7:

#include <stdio.h>
 
unsigned char i = 0;
int main()
{
    for(i = 0;i<=255;i++)
    {
        printf("hello wolrd\n");
    }
    return 0;
}
  • 看似是0 ~ 255一共循环256次,但是unsigned char类型最多表示的范围是255,无法跳出循环,所以循环判断条件是恒成立的
  • 255表示为0xff,如果此时在给它+1,变成2字节的01 00。因为char是一个字符,所以截断了高位,变成了0,又从起点开始循环了。

所以结果是:死循环

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

giturtle

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值