C语言进阶——数据在内存中的存储(一)

目录

数据类型的基本归类

数据类型的介绍

数据类型的意义

基本归类

整形在内存中的存储

补码  

举个“栗子”:

unsigned  char 和 signed char

为什么是补码

大端 小端

实例:判断当前机器的字节序:


 

实例:判断当前机器的字节序:


数据类型的基本归类

数据类型的介绍

在学习一定的C语言初阶知识后,我们知道以下的基本数据类型:

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

数据类型的意义

1.使用这个类型开辟内存空间的大小

  在我们定义一个数据后,会在内存中动态分配一块内存来存储这个数,这快内存需要分配多大的空间就由定义的数据的类型决定。

2.如何看待内存空间视角

   在写入数据后,在读取这块内存空间时,我们需要根据不同的数据类型去读取这块内存。

基本归类

整形类型:
	char
		unsigned char  //注意:char类型存储的是ASCII值因此归为整形
		signed char    //C语言并没有规定char是unsigned还是signed的
	short    
                unsigned short [int]
                signed short [int]
	int 
                unsigned int
                signed int
	long
                unsigned long [int]
                signed long [int]

浮点型:
        float
        double

//以下为了解内容,本文不做重点讲解	
构造类型(自定义):
        数组
            #include<stdio.h>
            int main()
            {
	        int arr[10];  // int [10]  这就是一种类型
	        int arr2[5];   //int [5]     另一种类型
	        return 0;
            }

	struct 结构体类型
	enum  枚举
	union 联合体
	
指针类型:
	int* pi
        char* pc
        float* pf
        void* pv

空类型:
        void
	函数返回类型  void test()
	函数参数     void test(void)
        指针         void* p

整形在内存中的存储

数据在内存中是以二进制的形式存在

对于整数 :在内存中以补码形式存储(为什么以补码的形式存储,我们先了解以下知识)

补码  

计算机中整数分无符号数和带符号数两种,带符号指的是数的第一位 为它的符号位,0代表正数,1代表负数,无符号数则没有符号位之分,全部为正数。

带符号数有三种形式 :原码、反码、补码

三种形式的都由两部分组成:符号位:数值的第一位,代表数据的正负,0代表正,1代表负

                                               数值位:原码,补码,补码在数值位有区别

   正整数的原码、反码、补码都相同

   负整数的补码需要计算,方法如下:

    原码-------------------------------------------------------------------反码--------------------------------------------------------补码

(直接按正负写出)                  (符号位/第一位不变,其他位取反——0变1.1变0;)                         (反码加一)

举个“栗子”:

#include<stdio.h>
int main()
{
	int a = -10;
	//原码:10000000 00000000 00000000 00001010  写出二进制序列即可,负数第一位为1
	//反码:11111111 11111111 11111111 11110101  第一位不变,其他按位取反
	//补码:11111111 11111111 11111111 11110110  加一
	return 0;
}

unsigned  char 和 signed char

前面提到char类型在内存中以转换的ascii码整数类型存储,所以也算是整型家族。

无符号的char类型:与正整数一样,只能表示正数,范围在0-255

带符号的char类型:

①规定的1000 0000为-128,不能按上述计算,因为会导致进位溢出,所以人为规定。

②范围:-128——127

图解如下:

为什么是补码

在明白补码是什么之后,你是否也有疑惑,为什么不是原码存储,而是选择复杂的补码呢?

原因如下:

使用补码,可以将符号位和数值位统一处理;

CPU只有加法器,在计算减法时,需要转化成加负数;

补码与原码相互转换,运算过程相同(即取反,在+1),不需要额外的硬件电路,运用取反电路和加法电路即可完成。

例子:

#include<stdio.h>
int main()
{
	int a = 10;
	int b = -10;
	//原码计算:
	//10:00000000 00000000 00000000 00001010
   //-10:10000000 00000000 00000000 00001010
  //等于:100000000 00000000 00000000 00010100  -20显然错误
	//补码计算:
	//10: 00000000 00000000 00000000 00001010
   //-10: 11111111 11111111 11111111 11110110
   //等于 00000000 00000000 00000000 00000000   结果为0,正确
	return 0;
}

大端 小端

在知道了整数是以二进制补码的形式存储后,还有一个问题需要解决。整型多字节时,需要不止一个存储单元存放,在存储单元中有两种分配方式

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

如图就是大端的存储方式:

将00000001放入,将低位的01放在高地址,类比可知将01放在低地址就是小端存储,不同的存储模式在不同的编译器中是不同的。

实例:判断当前机器的字节序:

设计一个程序判断当前机器的字节序(即判断是大端存储还是小端存储)。

#include<stdio.h>
int main()
{
	int a = 1;
	char* p =(char*) &a;//int型强转为char型,只观察一个字节
	if (*p == 1)//首地址是1,即为小端
	{
		printf("小端");
	}
	else  //为0为大端
	{
		printf("大端");
	}
	return 0;
}

优化:设计一个函数实现

int check_sys()
{
	int a = 1;
	return *(char*)&a;//返回1表示小端,返回0表示大端
}
int main()
{
	int ret = check_sys();
	if (ret == 1)
	{
		printf("小端\n");
	}
	else
	{
		printf("大端\n");
	}
	return 0;
}

 

Guess you like

Origin blog.csdn.net/m0_47646784/article/details/117223805