不同类型的整形在内存中存储时带来的问题

博客介绍了整形在内存中的截断与提升现象。当长字节整形赋值给短字节整形变量会截断,短字节整形用长字节整形输出会提升。表达式计算时,整形先提升为int类型,不足则提升为unsigned int类型。还通过几个简短代码说明了不同情况下的输出结果及可能出现的死循环问题。

由于整形在内存中拥有不同的类型,当把一个字节较长的整形数值赋给一个字节较短的整形变量会出现整形截断,而当将一个字节较短的整形变量用一个字节较长的整形变量输出时则会出现整形提升。在表达式计算时,各种整形首先要提升为int类型,如果int类型不足以表示则要提升为unsigned int类型,然后执行表达式的运算。
这里写图片描述

下面以几个简短的代码来说明问题:

一、
#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;
}

在vs编译环境下认为char为有符号的,所以a、b的输出结果相同。
-1在内存中的存储是按其二进制补码存放,格式如下:

11111111 11111111 11111111 11111111

又因为在vs编译环境下数据是按照小端存放的,所以char中只存放了-1的低八位二进制数字

11111111

而后面的打印格式却要求以整形输出,则进行整形提升有符号位补符号位,无符号位补0,所以a、b补全后还原为

11111111 11111111 11111111 11111111

即输出-1
而c在补全的时候无符号位,补0

00000000 00000000 00000000 11111111

则c输出255
这里写图片描述

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

-128在内存中的存放格式

11111111 11111111 11111111 10000000

放入char中的格式

10000000

以%u格式(无符号数格式)打印,但因char为有符号数,补全后还原为为

11111111 11111111 11111111 10000000

此时将此数当成无符号数,输出为
这里写图片描述
当然由于128在内存中的存放格式为

00000000 00000000 00000000 10000000

以上面的代码输出会出现同样的结果。

三、

当在循环的判断部分出现无符号数,则循环极有可能陷入死循环。

#include <stdio.h>
int main()
{
    unsigned int i;
    for (i=9; i>=0; i--)
    {
        printf("%u\n",i);
    }
    return 0;
}

当i从0降到-1时,存放格式为

11111111 11111111 11111111 11111111

但是编译器将此数当成无符号数(即2^33-1)为了便于观察,将输出格式定位%u,可以直观看到一个非常大的数字迅速递减的变化。

#include <stdio.h>
int main()
{
    unsigned char i = 0;

    for (i=0; i<=255; i++)
    {
        printf("hehe\n");
    }

    return 0;
}

当i加到256时存放格式为

00000000 00000000 00000001 00000000

截断放到无符号位的char中仍为0,累加继续,故陷入死循环。

四、
#include <stdio.h>
#include <string.h>
int main()
{
    char a[1000];
    int i;
    for (i=0; i<1000; i++)
    {
        a[i] = -1-i;
    }
    printf("%d\n", strlen(a));
    return 0;
}

因为char的表数范围是-128~127
i从0加到127,a[i]从-1减到-128
-128再减1为-129,其存放格式为

11111111 11111111 11111111 01111111

截断后放入char中为

01111111

因其有符号位,则此数为127
i再从128加到255,a[i]从127减到0
而0前面的数字个数为255
这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值