C语言存储

基本类型

 

数据类型:

1.char(字符类型通常归类于整形)

short

int(在16位平台下的大小是2;在32位平台下的大小是4,在64位平台下大小也为4)

long(对long的大小要求是>=4可以是4,可以是8)

long long(只有在C99标准下才支持)(不一定准确,我在Linux  C89 下测试了)

float

double

C89的基本类型,C99之后又增加了许多类型,如下图:        

 

 bool(_Bool):布尔类型(C99)

不过在C语言中0为假非0为真,在C语言可以没有布尔类型

 整形家族:

char(不等价于signed char)(取决于编译器)(常见的编译器等价于signed char):signed char(有符号字符)    unsigned char(无符号字符)

int(整型):  singed int     unsinged int(无符号数即使用负数赋值,它也是个正数)

short  [int](短整型):unsigned short     signed short

long  [int](长整型):unsigned long    signedlong

浮点型类型

float(单精度浮点数,占4个字节),double(双精度浮点数,占8个字节)如果创建的数对精度要求比较高可以用double

 构造类型(自定义类型)

数组类型(自定义类型):int [5],int [10],char [5]

结构体类型(自定义类型)

枚举类型(自定义类型)

联合类型(自定义类型)

 指针类型

char *pc;

int * pi;

float *pf;

void *pv

void 意为空类型或无类型;通常用于函数返回类型,函数的参数,指针类型

 整型在内存中的存储

内存中的数据的真实排布,是以十六进制的形式展示的 

右侧的乱码是内存中的数据翻译成文本,没有特别大的考虑意义

 整数的二进制的三种表现形式:

源码,反码,补码

而内存中存的是补码

正数的源码,反码,补码是相同的

负数:

源码:按照二进制直接写就是原码

反码:   符号位不变,其它位按位取反

补码:反码的二进制序列加1就是补码

~与反码的不同:~是连符号位都按位取反(每个位都按位取反)

为什么整数在内存中存的都是补码?

在计算机系统中,数值一律用补码来表示和存储。原因在于,使用补码,可以将符号位和数值域统
一处理;
同时,加法和减法也可以统一处理(CPU只有加法器)此外,补码与原码相互转换,其运算过程
是相同的,不需要额外的硬件电路。

 1 - 1可以写为1 +(-1)

大小端字节序

 大端字节序存储:数据的低权值(数据的大数位)位放在高地址处,高权值位放在低地址处

小端字节序存储:数据的高权值位放在高地址处,低权值位放在高地址处

为什么会有大小端?

为什么会有大小端模式之分呢?这是因为在计算机系统中,我们是以字节为单位的,每个地址单元都对应着一个字节,一个字节为8 bit。但是在C语言中除了8 bit的char之外,还有16 bit的short 型,32 bit的long型(要看具体的编译器),另外,对于位数大于8位的处理器,例如16位或者32位的处理器,由于寄存器宽度大于一个字节,那么必然存在着一个如何将多个字节安排的问题。因此就导致了大端存储模式和小端存储模式。
例如:一个 16bit 的 short 型 x ,在内存中的地址为 0x0010 , x 的值为 0x1122 ,那么 0x11 为 高字节, 0x22 为低字节。对于大端模式,就将 0x11 放在低地址中,即 0x0010 中, 0x22 放在高地址中,即 0x0011 中。小端模式,刚好相反。我们常用的 X86 结构是小端模式,而 KEIL C51 则为大端模式。很多的ARM,DSP都为小端模式。有些ARM处理器还可以由硬件来选择是大端模式还是小端模式。

百度系统工程师面试题:

什么是大小端,如何验证大小端?

大端字节序存储:数据的低权值(数据的大数位)位放在高地址处,高权值位放在低地址处

小端字节序存储:数据的高权值位放在高地址处,低权值位放在高地址处

代码如下:

#include<stdio.h>
#include<stdbool.h>
int main()
{
	int a = 1;
	char* p = (char*)&a;
	if (*p == 1)
	{
		printf("小端\n");
	}
	else
	{
		printf("大端\n");
	}
    return 0;
}

练习

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;
}

将a,b,c都输出到屏幕上,以(整数)%d的形式打印,要发生整形提升,char a 默认有符号位(VS2019),整形提升是补1(内存中的补码),因此a和b整形提升后内存中的值是11111111111111111111111111111111(补码)即为-1,c为无符号char,整形提升默认要补0,内存存储的是00000000000000000000000011111111(补码),因此c为255.

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

char a=-128;在内存中是10000000;整形提升补1,即11111111111111111111111110000000

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

128放在char a变量中存储在内存中也是1000 0000,整形提升后也是11111111111111111111111110000000.

4.
int i= -20;
unsigned  int  j = 10;
printf("%d\n", i+j); 
//按照补码的形式进行运算,最后格式化成为有符号整数

i发生算术转换后,补码相加结果再以有符号整数的结果打印出来,故为-10;

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

9,8,7,6,5,4,3,2,1,0,后会打印很大的数,i是无符号数,因此比较始终认为i>=0;

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

255,-1的补码11111111,-2的补码11111110,-3的补码11111101,,直到最后会变为00000000;strlen计算的是11111111到00000001的数,遇到00000000停止。

7.
#include <stdio.h>
unsigned char i = 0;
int main()
{
    for(i = 0;i<=255;i++)
   {
        printf("hello world\n");
   }
    return 0;
}

死循环的打印hello world。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值