详细介绍:C语言数据的存储

目录

1、数据类型介绍

1.1类型的基本归类

整形家族:

浮点型家族

构造类型:

指针类型

空类型:

2、整型在内存中存储

2.1 源码、反码、补码

2.2 大小端介绍

什么大端小端:

为什么有大小端?

2.3 练习

3、浮点型在内存中存储

3.1例子:

3.2浮点数存储规则


本章重点

1.数据类型详细介绍

2.整形在内存中存储:源码、反码、补码

3.大小端字节序介绍及判断

4.浮点型在内存中存储解析

1、数据类型介绍

C语言中内置类型:

char字符数据类型1字节
short短整型2个字节
int整形4个字节
long长整型4/8字节;32位机器上4个字节64位机器上8个字节
long long 更长的整型8个字节(c99出现的long long)
float单精度浮点数4字节
double双精度浮点数8字节

类型的意义:

1、使用这个类型开辟内存空间的大小(大小决定了使用范围)

2、如何看待内存空间的视角。

1.1类型的基本归类

整形家族:

char 

        unsigned char

        signed char

short

        unsigned  short [int]

        signed short [int]

int

        unsigned  int

        signed  int

long 

        unsigned  long

        signed long

long long

        unsigned long long [int]

        signed long long [int]  

char 字符类型的本质是ASCII码值,是整型,所以划分到整型家族。

char到底是signed char还是unsigned char标准是未定义的,取决于编译器的实现。

有符号和无符号的意义:

        在生活中有些数据是没有负数的,比如身高、体重、长度等。

浮点型家族

        float.

        double

浮点类型家族:只要是表示小数就可以使用浮点型。flaot的精度低,存储的数值范围较小,double的精度高,存储的数据的范围更大。

构造类型:

数组类型

结构体类型 struct

枚举类型 enum

联合类型 union

构造类型(自定义类型):我们可以自己创建出新的类型。

指针类型

int* pi;

char *p;

void *p;

空类型:

void 表示空类型(无类型)

通常应用于函数的返回类型,函数的参数,指针类型。

//第一个void表示函数不会有返回值
//第二个void表示函数不需要传参数。
void test(void){  //一个函数
}

2、整型在内存中存储

我们之前提到过一个变量的创建是要在内存中开辟空间的。空间的大小是根据不同的类型而决定的。

        接下来我们谈一谈数据在所开辟内存中到底是如何存储的?

比如:

        int a = 20;

        int b = -10;

 我们知道为a分配四个字节的空间。

那如何存储?

下来了解下面的概念:

2.1 源码、反码、补码

计算机中的整数有三种2进制表示方式,即源码、反码和补码。

        三种表示方式均有符号位数值位两部分,符号位都是用0表示“正”,用1表示“负”,而数值位正数的源、反、补码都相同。

负整数的三种表示方式各不相同。

源码:

直接将数值按照正负数的形式翻译成二进制就可以得到源码。

反码:

将源码的符号位不变,其他位依次按位取反就可以得到反码。

补码:

反码 +  1 就是补码。

对于整形来说:数据存放内存中其实存放的是补码。

为什么呢?

        在计算器系统中,数值一律用补码来表示和存储。原因在于,使用补码,可以将符号位和数值域统一处理;

        同时,加法和减法可以统一处理(cpu只有加法器)此外,补码与源码相互转换,其运算过程是相同的,不需要额外的硬件电路。(源码和补码相互转换都是取反 + 1)。

例如:计算1 - 1——> 1 + (- 1)

00000000 00000000 00000000 00000001——>1的补码

11111111   11111111   11111111   11111111——>-1的补码

相加:

1 00000000 00000000 00000000 00000000——>33位了,截断得到结果为0。

我们看一下再内存中的存储:

我们可以看一下a存储的补码。但是发现存储的顺序有点不对劲

这是为什么呢?

2.2 大小端介绍

什么大端小端:

    大端(存储)模式,是指数据的低位保存在内存的高地址,而数据的高位,保存在内存的低地址中;

        小端(存储)模式,是指数据的低位保存在内存的低地址中,而数据的高位,保存在内存的高地址中。

为什么有大小端?

        这是因为在计算机系统中,我们是以字节为单位的,每个地址单元都对应着一个字节,一个字节为8bit。但是在C语言中除了8bit的char之外,还有16bit的short型,32bit的long型(要看具体的编译器),另外,对于位数大于8位的处理器,例如16位或者32位处理器,由于寄存器宽度大于一个字节,那么必然存在着一个如何将多个字节安排的问题。因此就导致了大端存储模式和小端存储模式。

        例如:一个16bit的short型x,在内存中的地址0x0011,x的值为0x1122,那么0x11为高字节,0x22为低字节。对于大端模式,就将0x11放在地址值中,即0x0010中,0x22放在高地址中,即0x0011中。小端模式,刚好相反。我们常用的x86结果是小端模式,而KETL C51则为大端模式,很多的ARM,DSP都为小端模式,有些ARM处理器还可以由硬件来选择是大端模式还是小端模式。

百度2015年系统工程师笔试题:

请简述大端字节和小端字节序的概念,设计一个小程序来判断当前机器的字节序(10分)。

代码1:

int check_sys() {
	int i = 1;
	return *((char*)&i);
}
#include
int main() {
	int ant = check_sys();
	if (ant == 1) {
		printf("小端");
	}
	else {
		printf("大端");
	}
	return 0;
}

代码2:利用联合(共用体)

union un {
	int i;
	char c;
}s;
int check_sys(union un* s) {
	s->i = 1;
	return s->c;
}
#include
int main() {
	int ant = check_sys(&s);
	if (ant == 1) {
		printf("小端");
	}
	else {
		printf("大端");
	}
	return 0;
}

2.3 练习

有符号的char取值范围 -128 - 127

无符号的char的取值范围是 0 - 255

有符号的short的取值范围 - 32768 ~ 32767

无符号的short的取值范围 0 ~ 65535

练习1:

练习2:

练习3:

练习4:

代码5:

代码5出现死循环。

代码6:

strlen是求字符串的长度,关注的是字符串中‘\0‘(就是0)之前出现多少字符。

代码7:

死循环:原因是因为无符号char类型范围在0 - 255不可能下于255,。所以出现死循环。

代码8:

        如果比较两个字符串的长短可以直接比较不要用相减;strlen("abc") < strlen("abcv").或者强制类型转换为int类型。

3、浮点型在内存中存储

常见的浮点数:

3.14159

1E10

浮点数家族包括:float、double、long double(在C99中引用的)类型

浮点数表示的范围:float.h中定义。

3.1例子:

#include
#include
#include
unsigned char i = 0;
int main(){
	int n = 9;
	float* pFloat = (float*)&n;
	printf("n的值为:%d\n", n);
	printf("*pFloat的值为:%f\n", *pFloat);;
	*pFloat = 9.0;
	printf("num的值为:%d\n", n);
	printf("*pFloat的值为:%f\n", *pFloat);
}

3.2浮点数存储规则

对于float类型:

对于double类型:

 E全为1

posted on 2025-09-30 09:55  slgkaifa  阅读(12)  评论(0)    收藏  举报

导航