iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >C语言中数据在内存如何存储
  • 885
分享到

C语言中数据在内存如何存储

2024-04-02 19:04:59 885人浏览 薄情痞子
摘要

目录数据类型类型的基本归类整形有符号数和无符号数是否char 等于signed char呢?浮点型构造类型(自定义类型)指针类型空类型整形在内存中的存储原码,反码,补码正整数负整数大

数据类型

常见的数据类型

常见的数据类型 字节
char 字符数据类型 1
short 短整型 2
int 整形 4
long 长整型 4
long long 更长的整形 8
float 浮点型 4
double 双精度浮点型 8

注意:

  • C语言里面没有字符串类型
  • 关于int和long的大小:C语言只是规定了:sizeof(long)>=sizeof(int)
  • 布尔类型(_Bool)(C99引入)专门用来表示真假,但是在C语言中不需要布尔类型也可以表示真假

#include<stdbool.h>
int main()
{
    _Bool flag = false;
    _Bool flag2 = true;
    if(flag)
    {
        printf("haha\n");
	}
    if(flag2)
    {
        printf("hehe\n");
	}
return 0;
}//只打印了hehe

类型的基本归类

整形

char也属于整形(每一个字符在储存的时候是储存他所对应的ascll值,ascll是整数)

char unsigned char signed char
short unsigned short signed short
int unsigned int signed int
long unsigned long signed long

有符号数和无符号数

有符号数

int main()
{
	int a = 10;
    int a = -10;
	return 0;
}//a是一个有符号数,它可以储存正负整数

//int ===> signed int
//short ===> signed short
//long ===> signed long

无符号数

有一些变量只有正数由意义,例如年龄,价格。定义这些变量的时候就可以用无符号数定义 ,无符号数只能存储正数。


int main()
{
    unsigned int a = 10;
    //无符号变量只能储存正数
    a = -10;
    //即使这里输入了一个负数,它也会把这个负数转化成一个正数(不是简单的去掉符号,这是关于二进制的计算)
    return 0;
}

是否char 等于signed char呢?

答案:取决于编译器

  • 我们会发现这样一件事:
    int 就是 signed int
    short 就是 signed short
    long 就是 signed long
  • char 等于signed char还是unsigned char 取决于编译器,不同的编译器可能是不同的结果,常见的编译器下是等于signed char
对于有符号数字和无符号数字的打印

打印无符号数应该用%u

%u和%d打印的解读方式不同:

  • 使用%d 时,会认为这是一个有符号数,打印的时候会认为二进制中第一位是符号位;
  • 使用%u时,会认为这是一个无符号数据,会认为整个二进制序列都是有效位。

#include<stdio.h>
int main()
{
    unsigned int a = 10;
    printf("%u",a);//正确的形式
    
    //如果存储了一个-10进去会怎么样
    a = -10;
    printf("%u",a);
    //会打印4294967286,而这个数据不是随机数
    return 0;
}

为什么无符号整形储存 -10 的时候会打印出来4284967286(并不是随机数)?

%u在解读的时候认为此时a仍然存储的是正数,解读了a的补码。在本章后面介绍原反补吗的时候在详细解释细节。

浮点型

浮点型 大小
float 4
double 8

构造类型(自定义类型)

构造类型
数组 数组名去掉后剩下的就是数组的类型
结构体 struct
枚举类型 enum
联合(联合体)类型 uNIOn

指针类型

指针类型
char* pc
int * pi
float* pf
void* pv

空类型

void表示空类型(无类型)

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

整形在内存中的存储


int a = 10;
int b = -10;

然后我们观察a、b在内存中的储存

数据在内存里面是以二进制储存的,但是编译器是以十六进制展现给我们看的:

a在内存中的值是 :0a 00 00 00

b在内存中的值是: f6 ff ff ff

为什么是这样的值呢?下面介绍整数的原码、反码、补码。

原码,反码,补码

整数二进制有3种表示形式,而内存中存储的是二进制的补码

例如 1 的原码:

00000000 00000000 00000000 00000001

正整数

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

负整数

  • 原码:按照一个数的正负直接写出来的二进制就是原码
  • 反码:符号位不变,其他位按位取反 (并不是按位取反)
  • 补码:反码的二进制序列加1

从原码转换成补码:先取反再加一。

从补码转换成原码:可以先减一再取反,也可以先取反再加一(和原码转换成补码的过程相同)。

类型 数据:15 数据:-15
原码 00000000 00000000 00000000 00001111 10000000 00000000 00000000 00001111
反码 00000000 00000000 00000000 00001111 11111111 11111111 11111111 11110000
补码 00000000 00000000 00000000 00001111 11111111 11111111 11111111 11110001

解释为什么%u打印-10;会出现4294967286

用上面的方法我们就可以计算出-10的补码:

数据 补码
10 11111111 11111111 11111111 11110110

回到最开始使用%u打印-10会打印成4294967286,是因为在使用%u的时候,不会解读符号位,会将整个32位二进制都当作有效位,读出一个数据,而这个数据就是4294967286。

同时回到刚才a,b的值


int main()
{
int a = 10;
int b = -10;
    //a: 00000000 00000000 00000000 00001010
    //b: 11111111 11111111 11111111 11110110
}
//四个二进制位转换成一个十六进制位
//a: 00 00 00 0a
//b: ff ff ff f6

为什么和在内存界面看到的不同呢?

内存界面和我们计算出来的顺序是相反的:

数据 计算结果 内存
10 00 00 00 0a 0a 00 00 00
-10 ff ff ff f6 f6 ff ff ff

为什么会倒着存进去?

这就和字节序有关,下面我们来了解字节序

大小端字节序

当储存的内容超过一个字节的时候,储存的时候就有顺序

(一个char类型的数据是没有字节序。char类型的数据只有一个字节,没有顺序)

机器有两种对字节的存储顺序:

  • 大端字节序存储:
    低字节数据存放在高地址处,高字节数据存放在低地址处
  • 小端字节序存储
    低字节数据存放在低地址处,高字节数据存放在高地址处

我们用下面这个例子来解释:


int main()
{
    int a = 0x11223344;//0x开头说明是十六进制数字
    //再内存界面看到:44 33 22 11
   
    return 0;
}

而我在观察内存的时候发现我的机器是按照方式2进行存储的,所以我的机器是采用的小端字节序。

那么有什么方法可以快速判断自己当前使用的机器属于哪一种字节序呢?

设计一个小程序判断当前机器属于哪种字节序


#include<stdio.h>
int main()
{
    int a = 1;
    //a的十六进制是 00 00 00 01
    //如果是大端那么内存中为:00 00 00 01
    //如果是小端那么内存中为:01 00 00 00
    //只需要判断第一个字节的内容是不是1
    char*pc = (char*)&a;
    //强制类型转换截取了a的第一个字节
    if(*pc)//也可以是:if(*(char*)&a)
    {
        printf("小端");
	}
    else
    {
        printf("大端");
	}
        
	return 0;
}

储存时数据发生截断以及整型提升

例题1


int main()
{
	char a = -1;
	signed char b = -1;
	unsigned char c = -1;
	printf("%d %d %d ",a,b,c);//会打印出-1 -1 255
    return 0;
}

解释:

  • 第一步:
    这里我们将三个相同的整数 -1 分别存进了两种类型的变量,(在我所使用的VS2019编译器下char和signed char等价),而这两种类型又都属于char类型
  • 第二步:
    char 类型的变量只能储存一个字节(8个比特位)大小的数据,但是 -1 是整形(包含32个比特位),
    这里就需要发生数据截断: -1 的二进制补码是11111111 11111111 11111111 11111111
    截断:将补码的最后八位赋值给变量a、b、c。
  • 第三步:
    这里需要将char类型的数据以%d的方式打印,但是%d只能解读整数数据(整数有四个字节),而char类型的三个变量都只有一个字节,所以这里会发生整型提升:
    整形提升:对于有符号数据,高位补符号位,对于无符号数据:高位补0
数据(变量) 整形提升前 整形提升后(补码) 原码代表的数据
a/b 11111111 11111111 11111111 11111111 11111111 -1
c 11111111 00000000 00000000 00000000 11111111 255

%d打印的时候会认为这就是要打印数据的补码,按照打印正常整数的形式打印这三个变量

例题2


#include<stdio.h>
int main()
{
    
    char a = -128;
    printf("%u",a);//会打印4294967168
    return 0;
}

解释:

  • 第一步:
    观察数据: -128 是一个整数,二进制有32位 : 但是接受这个数据的变量是一个char类型的变量(只能接受8个比特位)
  • 第二步:
    数据的截断:
数据 二进制(补码) 截取(a储存的部分)
-128 11111111 11111111 11111111 10000000 10000000

联想:这里如果是a = 128,那么阶段后的值仍然是10000000

  • 第三步:
    打印整数(四个字节),所以这里需要发生整形提升(a是有符号char,高位补符号位)
数据(变量) 整形提升前 整形提升后(补码)
a 10000000 11111111 11111111 11111111 10000000
  • 第四步:
    %u的形式打印这个变量,因为%u应该打印的是无符号整数,且打印的时候认为整个32位全为有效位,
    就会打印出4294967168

浮点型在内存中的存储

常见的浮点数 例子
字面浮点数 3.14159
科学计数法的表示形式 1E10(1乘以10的10次方)

注意:

  • 在浮点型数据后面加了f是float类型,不加则默认是double类型
  • %f和%lf默认小数点后六位

浮点型和整形在内存中的储存方式不同

我们通过下面这个例题来探究浮点型和整形在内存中的储存方式有什么不同


#include<stdio.h>
int main()
{

	int n = 9;
	float* pf = (float*)&n;
    //第一组
	printf("n = %d\n", n);    //打印出:9
	printf("*pf = %f\n", *pf);//打印出:0.000000
	//第二组
	*pf = 9.0;
	printf("n = %d\n", n);	  //打印出:1091567616
	printf("*pf = %f\n", *pf);//打印出:9.000000

	return 0;
}

为什么会出现这样的情况?

回答这个问题前,先来了解浮点型的二进制存储形式:

国际标准电气电子工程师学会(IEEE):任何一个二进制浮点数V都可以表示成下面的形式

  • 表示形式:(-1)^S * M * 2^E
  • (-1)^S表示符号位,当S为0 时表示正数,当S为1时,表示负数
  • M表示有效数字,大于等于1,小于等于2
  • 2^E表示指数位
(5.5)十进制 (5.5)二进制
5.5 101.1
5.5*(10^1) 1.011*(2^2)

十进制浮点数:5.5
转化成二进制:101.1
可以写成:(-1)^0 * 1.011 * (2^2)
S = 0
M = 1.011
E = 2
只需要储存SME三个值
  • IEEE浮点数标准定义了两种基本的格式:以四个字节表示的的单精度格式和八个字节表示的双精度格式

单精度浮点数储存格式(32位)

第一位 接着8位 剩下23位
符号位 指数位 有效位

双精度浮点数储存格式(64位)

第一位 接着11位 剩下52位
符号位 指数位 有效位

IEEE754对于有效数字M和指数E有一些特别的规定:

  • 关于M:
    1.我们已经知道1<=M<2,也即是说M一定可以写成这样的形式:1.xxxxxx
    其中xxxxxx表示小数点后面的部分
    2.在计算机内部储存M时,由于第一位总是1,所以把这个1省略,只保存后面的小数部分,这样可以节约一位有效数字,这样的话储存的数据精度就可以提升一位:例如在单精度浮点型存储格式中,最后23位作为有效位,但是储存在计算机的数据精度是24位
  • 关于E:
    计算机会认为这是一个无符号数,但是十几行会存在很多E取负数的情况,所以IEEE754规定:存入内存时,E的真实值必须在加上一个中间数 ,对于单精度,这个中间数(也叫做偏移量)是127,对于双精度,这个中间数是1023
    例如:对于十进制的数字0.5,它的二进制是0.1,E= -1;那么我们就需要把-1在加上127得到126后,将126储存在指数位

拿出这些储存的数据(三种情乱)

情况一:E不全为0或不为全1

  • E: 指数位值减去127(1023)得到真实值
  • M: 有效位的数值前面加上1.

情况二:E全为0

  • E:
    真实的E是一个十分小的数字,接近0;
    这时候不用计算,E直接就等于1-127(1-1023)就是它的真实值
  • M:
    M不再在前面加上1,而是还原成0.XXXXXX的小数,这样做是为了表示正负0,以及接近于0的很小的数字。

情况三:E为全1

  • 真实的E是一个十分大的数字,代表正负无穷大的数字

解释上面的例子

  • 第一组为什么以%f打印整数9,会打印出0.000000?

原因:

此时E为全0,是一个会被判定成一个十分小的数据,所以打印0.000000

  • 为什么第二组中以%d的形式打印*pf时,会打印出1091567616?

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程网。

--结束END--

本文标题: C语言中数据在内存如何存储

本文链接: https://www.lsjlt.com/news/159458.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • C语言中数据在内存如何存储
    目录数据类型类型的基本归类整形有符号数和无符号数是否char 等于signed char呢?浮点型构造类型(自定义类型)指针类型空类型整形在内存中的存储原码,反码,补码正整数负整数大...
    99+
    2024-04-02
  • C语言数据在内存中的存储
    这篇文章主要介绍了C语言数据在内存中的存储,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。数据类型详细介绍在前面C语言基础概览中,已经提到过了基本的C语言内置类型,但C语言的数...
    99+
    2023-06-15
  • C语言中数据是如何存储在内存中的
    目录前言‍数据类型介绍‍整形数据在内存中存储‍浮点型数据在内存存储前言 在计算机内存中,数据的存储方式都是以0和1的形式存储,也就是二进制的形式,数据是如何向...
    99+
    2024-04-02
  • C语言数据在内存中的存储详解
    目录文章摘要一、C语言的数据类型数据类型基本分为: 二、隐式类型转换1.什么是隐式类型转换2.整型提升 3.类型转换三、机器大小端1.什么是大小端2.大小端在截断的应用3....
    99+
    2024-04-02
  • C语言数据在内存中是怎样存储的
    这篇文章主要介绍“C语言数据在内存中是怎样存储的”,在日常操作中,相信很多人在C语言数据在内存中是怎样存储的问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”C语言数据在内存中是怎样存储的”的疑惑有所帮助!接下来...
    99+
    2023-06-08
  • C语言中数据在内存中是怎么存储的
    本篇文章为大家展示了C语言中数据在内存中是怎么存储的,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。数据类型常见的数据类型常见的数据类型字节char字符数据类型1short短整型2int整形4long...
    99+
    2023-06-22
  • C语言数据(整数、浮点数)在内存中的存储
    本篇主要讨论:整数、浮点数在内存中是怎么保存的! 数据类型详细介绍 在前面C语言基础概览中,已经提到过了基本的C语言内置类型,但C语言的数据类型有无数种~ 但是可以把这些类型分为几个...
    99+
    2024-04-02
  • C语言编程数据在内存中的存储详解
    目录变量在计算机中有三种表示方式,原码反码,补码原码反码补码总结一下浮点数在内存的储存C语言中,有几种基本内置类型。 int unsigned int signed int cha...
    99+
    2024-04-02
  • 关于C语言中数据在内存中的存储详解
    目录前言一、数据类型介绍1.类型的基本归类1.整形家族2.浮点型家族3.构造类型4.指针类型5.空类型二、整型在内存中的存储1.原码、反码、补码2.内存中怎样存储3.大小端字节序1....
    99+
    2024-04-02
  • C++浅析数据在内存中如何存储
    目录一、数据类型二、原码反码补码三、大小端整型提升一、数据类型 数据类型有7种:    char         ...
    99+
    2022-11-13
    C++数据存储 C++数据在内存中存储
  • C语言数据在内存中的存储流程深入分析
    目录前言类型的基本分类整型浮点数自定义类型整型在内存中的存储原码、反码、补码大端和小端如何判断编译器是大端还是小端浮点数在内存中的存储总结前言 C语言中有char、short、int...
    99+
    2022-11-13
    C语言数据在内存中的存储 C语言数据存储
  • C语言详细分析浮点数在内存中的储存
    目录浮点数的储存格式初步了解深入探究E不全为0或不全为1E全为0E全为1浮点数的储存格式 初步了解 首先让我们通过一段代码来认识一下浮点型和整型的区别: int main() { ...
    99+
    2024-04-02
  • C语言浮点型数据在内存中的存储方式是什么
    本篇内容介绍了“C语言浮点型数据在内存中的存储方式是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!一、思考一下咱们先上一盘开胃菜,试试看...
    99+
    2023-07-05
  • 如何分析C语言数据的存储
    如何分析C语言数据的存储,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。数据类型的介绍数据类型存在的意义为变量开辟的空间大小(大小决定了使用范围)取数据的时候按照...
    99+
    2023-06-22
  • Go 语言中的数组和打包:如何在内存中存储和管理数据?
    Go 语言是一种编译型、并发的、静态类型的语言,它支持面向对象、函数式、过程式和并发编程等多种编程范式。在 Go 语言中,数组和打包是两个非常重要的概念,它们对于内存的管理和数据的存储都起着至关重要的作用。本文将介绍在 Go 语言中如何使...
    99+
    2023-07-01
    存储 数组 打包
  • C语言数据存储详解
    目录一、数据类型二、整型在内存中的存储1.原码、反码、补码大小端介绍三、浮点型在内存中的存储1.举一个浮点数存储的例子: 2.浮点数存储规则: 总结一、数据类型 char:字符数字类...
    99+
    2024-04-02
  • 详解C语言中数据的存储
    目录一、类型归类1、整形家族2、浮点型家族3、指针类型4、空类型二、类型的意义 三、数据在类型中存储(以整形和浮点型为例子)1. 关于 存储的基本概念2.存储模式四.应用1.2.对...
    99+
    2024-04-02
  • C语言中数据的存储详解
    目录1.内置类型(1)整型数组(2)浮点型2.自定义类型3.指针类型4.空类型(void)字符型浮点型(一)(二)总结 数据的存储首先就要说到数据的类型,类型决定了看待内存空间的视角...
    99+
    2024-04-02
  • 如何在Go语言中高效存储数组数据?
    Go语言中的数组是一种基本的数据结构,它可以存储一组相同类型的数据。但是,对于大型数组的存储和操作,可能会导致性能问题。本文将介绍如何在Go语言中高效存储数组数据。 一、使用切片 Go语言中的切片是一个动态数组,可以根据需要自动扩展和收缩。...
    99+
    2023-11-06
    索引 数组 存储
  • c语言怎么将数据储存在文件中
    在C语言中,可以使用文件操作函数来将数据存储在文件中。以下是一个简单的示例:```c#include int main() {FIL...
    99+
    2023-08-15
    c语言
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作