c语言整型存储方式

        c语言中的数据类型主要分为字符型,整形和浮点型,字符在系统中存储的是ASCII码,所以也是整形。

char 			//字符数据类型
short			//短整型
int 			//整形
long			//长整型
long long		//更长的整形
float			//单精度浮点数
double			//双精度浮点数

各种数据类型的大小如下:

 printf("%d\n", sizeof(char));//1字节,8bit
 printf("%d\n", sizeof(short));//2字节,16bit
 printf("%d\n", sizeof(int));//4字节,32bit
 printf("%d\n", sizeof(long));//4字节,32bit或8字节,64bit,32位平台下4字节,64位平台下8字节,c语言规定sizeof(long)>=sizeof(int) 
 printf("%d\n", sizeof(long long));//8字节,64bit
 printf("%d\n", sizeof(float));//4字节,32bit
 printf("%d\n", sizeof(double));//8字节,64bit
 printf("%d\n", sizeof(bool));//1字节,8bit

整形在内存中的存储方式

原码反码补码

        有符号整形的最高位为符号位,0表示正数,1表示负数,整形的二进制有三种表示形式:原码、反码和补码,整型在内存中存储的是补码,因为CPU中只有加法器,这样可以把减法运算变成加负数的运算。最初的二进制形式就是原码,反码是将原码的符号位不变,其余位按位取反补码是将反码加一,所以原码得到补码需要先取反再加一,补码变回原码也可以先取反再加一,结果和先减一再取反一样,正整数的原码、反码和补码相同,下面来举个例子:

char a = 7;//这里的7是ascll码
//原码:00000111
//反码:00000111
//补码:00000111
//正数原反补相同
char b = -7;
//原码:10000111
//反码:11111000
//补码:11111001

大小端问题

        大端字节序存储:把一个数据的位字节序的内容存放在内存中的地址处,位字节序的内存存放在地址处。

        小端字节序存储:把一个数据的位字节序的内容存放在内存中的地址处,位字节序的内存存放在地址处。

      我们常用的x86结构是小端模式,而KEIL C51则为大端模式。很多的ARM,DSP都为小端模式。有些ARM处理器还可以由硬件来选择是大端模式还是小端模式。

判断当前编译器大小端的方法

#include "stdio.h"
#include "string.h"

int main()
{
    int i = 1;
    char *b = (char *)&i;
    if (*b == 1)
    {
        printf("小端\n");
    }
    else
    {
        printf("大端\n");
    }
    return 0;
}

        int类型的i为1,也就是0x00000001;如果是大端字节序,它在内存中的低地址会存放最高位,也就是00,如果是小端字节序,他在内存中的低地址会存放最低位,也就是01,对i取地址,取到的是四个字节的地址,然后强制转换成char*,得到的就是四个字节中最低字节的地址,然后解引用得到的就是最低的字节,如果是1就是小端,是0就是大端。

#include "stdio.h"
#include "string.h"
union u
{
    int a;
    char b;
};
int main()
{
    union u s;
    s.a = 1;
    if (s.b == 1)
    {
        printf("小端\n");
    }
    else
    {
        printf("大端\n");
    }
    return 0;
}

        联合体中成员共用地址,u.b用的是u.a的低地址,所以如果u.b为1就是小端,为0就是大端。

内存中的数据范围

        下面以signed char 和unsigned char类型来举例说明内存有无符号两种数据类型的存储范围:

        如果是无符号型,不需要考虑符号位,内存中的补码就是原码,char八位数据,全为1时就是255,范围是0到255

        对于有符号型比较复杂,第一位表示符号位,第一位为0时还是正常的0~127,01111111+1的话等于10000000,是补码,取反加一得到原码100000000,会多出一位,c语言规定这个数为-128,也就是127+1=-128, 10000001取反加一得到11111111,就是-127,可以理解,11111111取反加一得到原码10000001,就是-1,0-1 = -1。可以得出signed char范围是-128~127

练习

int main()
{
    signed char a = -1;
    unsigned char c = -1;
    printf("a = %d, c = %d",a,c);
}

        首先讲一个知识点,char类型在用%d打印时会发生整型提升,整型提升如果是有符号数就在前面加符号位,如果是无符号数就在前面加0。

int main()
{
    char a = -128;
    printf("%u\n",a);
    printf("%d\n",a);
}

         %u是将a当作无符号数打印,%d是当作有符号数打印。

 

int main()
{
    char a = 128;
    printf("%u\n",a);
    printf("%d\n",a);
}

int main()
{
    int i = -20;
    unsigned int j = 10;
    printf("%d",i + j);
}

int main()
{
    unsigned int i ;
    for(i = 9; i <= 0; i--)
    {
        printf("%u\n",i);
    }
}

         上述代码会死循环,因为i是无符号整型,只有正数,当i减到0时再减一补码会变成全1,因为时无符号类型,所以是一个很大的正数,不会出现负数也就不会跳出for循环。

int main()
{
    char a[1000];
    int i;
    for(i = 0; i < 1000; i++)
    {
        a[i] = -1 - i;
    }
    printf("%d",strlen(a));
}

int main()
{
    if(strlen("abc") - strlen("abcdef") >= 0)
        printf(">\n");
    else
        printf("<\n");
    return 0;
}

         strlen的返回值类型是size_t,也就是unsigned int,因为字符串长度不会是负数,但是在这里两个size_t类型的数相减,得到的结果类型也是size_t,虽然实际上会得到-3,但是作为无符号数来看就是一个很大的正数,所以结果不可能小于0,不能用上述方法来判断两个字符串长度大小。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值