C语言深入探索数据类型的存储

目录
  • 数据类型介绍
    • 类型的基本归纳
      • 整型家族
      • 浮点数家族
      • 构造类型
      • 指针类型
      • 空类型
  • 整型在内存中的存储
    • 原码,反码,补码
    • 大小端
  • 浮点数在内存中的存储
    • 浮点数存储的规则

数据类型介绍

首先,对于我们C语言中的数据类型,大家应该都有一个清晰的认识吧!如果不记得也没有关系哦~ 在这里来跟着小刘同学回顾一下吧!

关于数据类型,我们在前面已经学习过了一些内置数据类型,以及它们所占的内存空间的大小,例如:

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

那,在这里,我们需要思考一个问题:在C语言中存在字符串类型嘛?

这个问题的答案需要大家自己去思考哟~(当然,如果不知道的话可以私信小刘同学哟~

类型的意义:1.使用这个类型开辟的内存空间的大小,也就是说类型决定了我们可以使用的空间的大小。2.如何看待内存空间的视角。

类型的基本归纳

首先,当然是我们经常使用的整型类型家族啦!

整型家族

char //字符数据类型
    unsigned char //无符号字符型
    signed char //有符号字符型
short //短整型
     unsigned short[int] //无符号短整型
     signed short[int] //有符号短整型
int //整型
   unsigned int //无符号整型
   signed int //有符号整型
long //长整型
    unsigned long[int] //无符号长整型
    signed long[int] //有符号长整型

当然,整型家族当然是少不了我们的long long int 型的,但是由于更长长整型的分类与整型家族其他成员的分类是相似的,所以在这里我们不加赘述。

浮点数家族

float
double

构造类型

>数组类型
>结构体类型 struct
>枚举类型 enum
>联合类型 union

指针类型

int * pi;
char * pc;
float * pf;
void * pv;

空类型

void表示空类型(无类型)

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

整型在内存中的存储

首先,我们在之前的文章中谈到过,变量的创建是要在内存中开辟一部分空间的。而开辟的空间的大小是要根据不同的类型而决定的。那么,下面就跟着小刘同学一起来学习一下数据在它所开辟的内存中究竟是如何进行存储的吧!

我们先来举一个例子吧:

int a=10;
int b=-10;

我们知道,因为a为int型,所以为a分配了4个字节的空间,那么,在内存又该如何存储呐?

要想了解这一点,我们先来明白几个概念:

原码,反码,补码

在计算机中的整数存在3种2进制的表示方式:原码、反码、补码。

这三种方法均存在符号位和数值位这两个部分。符号位使用0表示'正',使用1表示'负'。而数值位正数的原码、反码、补码都相同。而负整数的三种表示方法都不相同。

原码

直接将数值按照正负数的形式转换成二进制的形式就可以得到原码。

反码

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

补码

在反码的基础上+1就可以得到补码。

对于整形来说,数据存放在内存中其实是以补码的形式存放的。(相信学过数电的小伙伴一定知道这是为什么。那么其他不知道所以然的小伙伴请自行百度询问哦。

在vs里面我们可以看到a和b在内存中的地址,但是,这样看是不是有点不太对?

按照我们上面所讲的内容,列出a和b在内存中存储的二进制形式再根据二进制转为十六进制的规则,a和b在内存中的存储应该是下图所示的形式,那么为什么我们在VS的调试中会出现不一样的结果呐?

int a=10;
//原码:0000 0000 0000 0000 0000 0000 0000 1010
//反码:0000 0000 0000 0000 0000 0000 0000 1010
//补码:0000 0000 0000 0000 0000 0000 0000 1010
// 00 00 00 0a
int b=-10;
//原码:1000 0000 0000 0000 0000 0000 0000 1010
//反码:1111 1111 1111 1111 1111 1111 1111 0101
//补码:1111 1111 1111 1111 1111 1111 1111 1010
//ff ff ff fa

这个时候,我们来再了解一个概念——大小端。

大小端

大小端指的是两种不同的存储方式。那么下面我们来详细了解一下什么是大小端:

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

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

当然,大端存储和小端存储是根据编译器的不同来决定的。

这样子只看概念大家是否感到十分疑惑呐?下面,小刘同学给大家画图模拟一下大端存储和小端存储的基本情况吧!

这样子,大家是不是对大端存储和小端存储有了一个基本的概念了解呐?

那么,大家现在是不是非常好奇自己目前使用的编译器究竟使用了那种存储方式呐?

下面请跟着小刘同学来判断一下自己所使用的编译器究竟是哪种存储方式吧!

我们首先定义一个变量:int a=1;

int a=1;
//原码:0000 0000 0000 0000 0000 0000 0000 0001
//反码:0000 0000 0000 0000 0000 0000 0000 0001
//补码:0000 0000 0000 0000 0000 0000 0000 0001
//如果是大端存储,返回的第一个字节一定为00 ——> 0
//如果是小端存储,返回的第一个字节一定为01 ——> 1

完整代码如下:

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

浮点数在内存中的存储

浮点数存储的规则

首先,我们来举一个例子

#include<stdio.h>
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);
	return 0;
}

以上代码执行的结果为:

它这个结果好像和我们想象的结果不太一样哎。这是为什么呐?在这里就不得不提一下浮点数在内存中的存储规则了。

根据国际标准IEEE(电气和电子工程协会) 754,任意一个二进制浮点数V可以表示成下面的形式:

  • (-1)^S * M * 2E
  • (-1)S表示符号位,当S=0,V为正数;当S=1,V为负数。
  • M表示有效数字,大于等于1,小于2。
  • 2^E表示指数位。

看到这里,大家是不是有很多的疑问和不理解?别急,下面小刘同学来为大家讲解清楚。

要想理解上面的内容,我们先来举一个例子吧!

例如:9.5f

小数点后面的权重是2的-1次方,-2次方这样子依次类推。

当然,并不是所有的浮点数都可以表示出来的,有的浮点数是无法表示出来的,小数点后面的数无法精确表示,可能会出现精度缺失。

IEEE 754对有效数字M和指数E,还有一些特别规定。

前面说过, 1≤M<2 ,也就是说,M可以写成 1.xxxxxx 的形式,其中xxxxxx表示小数部分。 IEEE 754规定,在计算机内部保存M时,默认这个数的第一位总是1,因此可以被舍去,只保存后面的xxxxxx部分。比如保存1.01的时候,只保存01,等到读取的时候,再把第一位的1加上去。这样做的目的,是节省1位有效数字。以32位浮点数为例,留给M只有23位,将第一位的1舍去以后,等于可以保存24位有效数字。

至于指数E,情况就比较复杂。

首先,E为一个无符号整数(unsigned int) 这意味着,如果E为8位,它的取值范围为0~255;如果E为11位,它的取值范围为0~2047。但是,我们知道,科学计数法中的E是可以出现负数的,所以IEEE 754规定,存入内存时E的真实值必须再加上一个中间数,对于8位的E,这个中间数是127;对于11位的E,这个中间 数是1023。比如,2^10的E是10,所以保存成32位浮点数时,必须保存成10+127=137,即 10001001。

在我们已经知道如何存储浮点数后,我们再来学习一下如何将浮点数从内存中取出。

指数E从内存中取出还可以再分成三种情况:

E不全为0或不全为1

这时,浮点数就采用下面的规则表示,即指数E的计算值减去127(或1023),得到真实值,再将有效数字M前加上第一位的1。 比如: 0.5(1/2)的二进制形式为0.1,由于规定正数部分必须为1,即将小数点右移1位,则为 1.0*2^(-1),其阶码为-1+127=126,表示为01111110,而尾数1.0去掉整数部分为0,补齐0到23位00000000000000000000000,则其二进制表示形式为:

//0 01111110 00000000000000000000000

E全为0

这时,浮点数的指数E等于1-127(或者1-1023)即为真实值, 有效数字M不再加上第一位的1,而是还原为0.xxxxxx的小数。这样做是为了表示±0,以及接近于0的很小的数字。

E全为1

这时,如果有效数字M全为0,表示±无穷大(正负取决于符号位s)。

以上及是数据存储的内容。另外,关于数据存储方面的一些补充和讲解

到此这篇关于C语言深入探索数据类型的存储 的文章就介绍到这了,更多相关C语言数据存储 内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

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

    目录 前言 ‍数据类型介绍 ‍整形数据在内存中存储 ‍浮点型数据在内存存储 前言 在计算机内存中,数据的存储方式都是以0和1的形式存储,也就是二进制的形式,数据是如何向内存写入的呢?整形数据以补码的形式存储,浮点型的存储规则较多,类似于科学计数法. ‍数据类型介绍 为什么需要有这些数据类型? 数据类型解决了数据存储的问题. ‍整形数据在内存中存储 整数中有三种二进制表示形式,分别是原码.反码.补码,正整数的原码 = 反码 = 补码,通常取最高位作为符号位. 原码:直接将正负整数按照二进制形式转换

  • C语言数据的存储专项分析

    目录 数据的类型介绍 类型的基本归类 整形在内存中的存储 源码.反码.补码 关于大小端的概念 浮点型在内存中的存储 数据的类型介绍 类型的基本归类 在写数据类型的介绍之前,我们首先来简单介绍下 release版本与debug版本之间的在内存上的区别: 我们先将下面的一段代码在VS中运行一下,得到的结果是截然不同的 int i = 0; int arr[] = { 1,2,3,4,5,6,7,8,9,10 }; for (i = 0; i <= 12; i++) { arr[i] = 0; pri

  • C语言详细图解浮点型数据的存储实现

    目录 在引入知识之前,先来看一个案例,就知道了解浮点型数据存储的重要性与必要性. 举个例子: #define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h> int main() { int num = 9; float *pnum = (float *)&num;//强制转换类型 printf("n的值为:%d\n",n); printf("*pFloat的值为:%f\n",*pnum); *pnum =

  • C语言进阶数据的存储机制完整版

    目录 数据类型 内存窗口 1.地址栏 2.内容 3.文本 整型的存储 原码,反码,补码 补码的意义 大小端模式 不同数据类型存储 浮点数存储机制 数据类型 1.基本内置类型:byte,int ,char, float, double 2.构造数据类型: 数组类型:结构体类型:struct共用体(联合类型):union枚举类型:enum 3.指针类型 :int* p,char* p,float* p,void* p 4.空类型 : void(无类型),通常用于函数的返回类型,函数参数与指针类型.

  • C语言中的字符串数据在C中的存储方式

    目录 内存中的五大区域 字符串数据在C语言中有两种存储方式 几个比较容易混的点 统计字符串中某一个字符出现的次数 使用字符指针数组来存储多个字符串数据 内存中的五大区域 栈:是专门用来存储局部变量的,所有的局部变量都是声明在栈区域中 堆:允许程序员手动的从堆申请指定字节数的空间来使用 BSS段:是用来存储未初始化的全局变量和静态变量,声明一个全局变量,如果我们没有初始化,在程序运行最开始的时候,这个全局变量是没有初始化的,存储在BSS段[程序运行后系统就自动的初始化为0,并把初始化后的全局变量存

  • C语言数据的存储超详细讲解上篇

    目录 前言 1.数据类型介绍 类型的基本归类 2.整形在内存中的存储 2.1 原码.反码.补码 2.2 大小端介绍 2.2.1 什么是大小端 2.2.2 大端和小端意义 2.2.3 写程序判断字节序 总结 前言 本文开始学习C语言进阶的内容了,进阶内容,是在基础阶段的内容上进行拓展,有的知识点,在基础阶段也已经学过.在进阶内容中,将从更深层次的角度去理解学习,本文主要内容包括: 数据类型详细介绍 整形在内存中的存储:原码.反码.补码 大小端字节序介绍及判断 浮点型在内存中的存储解析 1.数据类型

  • 深度解析C语言中数据的存储

    目录 前言 数据类型介绍 类型的基本归类 整型家族 浮点数家族 构造类型 指针类型 空类型 前言 在VS编译器里有release和debug两种形式,debug包含调试信息,release不包含调试信息,并会对程序进行优化 int main() { int i = 0; int arr[10] = { 1,2,3,4,5,6,7,8,9,10 }; for (i = 0; i <= 12; i++) { arr[i] = 0; printf("hehe\n"); } return

  • C语言数据的存储超详细讲解中篇练习

    目录 前言 数据的存储的知识点练习 练习 1 练习 2 练习 3 练习 4 练习 5 练习 6 练习 7 总结 前言 本文继续学习数据在内存中存储的相关知识点. 数据存储 整型提升 数据的存储的知识点练习 通过几个练习来深入学习数据在内存中存储的知识点,先复习前面学过的整形提升的知识点:C语言操作符超详细讲解下篇 整形提升是按照变量的数据类型的符号来提升的 负数的整形提升,最高位补充符号位,即1,例如 char a=-1;11111111 截断后的补码1111111111111111111111

  • C语言数据的存储详解

    目录 数据类型的介绍 整形 浮点型 构造类型 指针类型 void空类型 整数在内存中的存储 原反补的介绍 大小端的介绍 面试例题 练习 浮点数在内存中的存储 存储规则讲解 举例 IEEE754的特别规定 案例 float用%d打印的特例讲解 数据类型的介绍 数据类型存在的意义 为变量开辟的空间大小(大小决定了使用范围) 取数据的时候按照什么格式取出(先看大小端,在看数据类型(用来解析二进制数据的方式)) 整形 char unsigned char signed char short unsign

  • C语言深入探索数据类型的存储

    目录 数据类型介绍 类型的基本归纳 整型家族 浮点数家族 构造类型 指针类型 空类型 整型在内存中的存储 原码,反码,补码 大小端 浮点数在内存中的存储 浮点数存储的规则 数据类型介绍 首先,对于我们C语言中的数据类型,大家应该都有一个清晰的认识吧!如果不记得也没有关系哦~ 在这里来跟着小刘同学回顾一下吧! 关于数据类型,我们在前面已经学习过了一些内置数据类型,以及它们所占的内存空间的大小,例如: char         //字符数据类型int          //整型short      

  • 深入理解Python变量的数据类型和存储

      我们知道,python的变量是有类型的,对于python变量的几种数据类型,我们在写python时是必须要有一定的概念的.知道数据类型就要知道变量数据类型怎么存储,可是为什么python的变量不需要声明数据类型就可以直接赋值?变量如果有数据类型,那变量不是可以为任意数据类型?那真正的数据类型如int在内存存储的字节大小应该为多少?等等诸如一系列的问题让我提起了的兴趣,经过网上不断查找学习后,在此将我所了解到的内容在此做个总结归纳 一.变量的数据类型 1.什么是变量的数据类型   我们先捋一捋

  • PHP内核探索:变量存储与类型使用说明

    先回答前面一节的那个问题吧. 复制代码 代码如下: <?php    $foo = 10;    $bar = 20; function change() {        global $foo;        //echo '函数内部$foo = '.$foo.'<br />';        //如果不把$bar定义为global变量,函数体内是不能访问$bar的        $bar = 0;        $foo++;    } change();    echo $foo

  • C语言深入探索浮点数的使用秘密

    目录 一.内存中的浮点数 二.浮点数存储实例 三.浮点类型的秘密 四.小结 一.内存中的浮点数 浮点数在内存的存储方式为:符号位,指数,尾数 类型 符号位 指数 尾数 float 1位(第31位) 8位(第23--30位) 23位(第0--22位) double 1位(第63位) 11位(第52--62位) 52位(第0--51位) 注:float 与 double 类型的数据在计算机内部的表示法是相同的,但由于所占存储空间的不同,其分别能够表示的数值范围和精度不同. 二.浮点数存储实例 浮点数

  • C语言深入探索之单链表与typedef的用法

    目录 前言 详解typedef关键字 含义 具体使用 详解单链表参数形式 指针知识补充 单链表形参详解 单链表实战案例 完整代码实现 详解头插建表 运行效果 前言 昨天博主去本站问答贴子逛了逛,然后发现了好多关于数据结构线性表,具体来说是单链表的问题.有的是没有一点思路,无从下手:有的是看不懂代码,不理解关键字以及被形参的形式气的不行,我总结了一下常见问题来给大家带来干货,到后面还有简单案例来巩固知识,弄透一题胜无脑刷百题,接下来是正文内容. 详解typedef关键字 含义 C语言允许用户使用

  • go语言中基本数据类型及应用快速了解

    目录 整数 特殊的整数类型 如果想确定int和uint的大小 溢出 浮点数 复数 布尔值 字符串 字符串的“长度”与遍历字符串的做法 字符串的“长度” 遍历字符串 Rune与Byte(字节) 字符串与字节slice的转换 字符串不可变 基本类型的值都是可比较的 数值的类型转换 运算符 常量 整数 按位长度分度分为:8位,16位,32位,64位. 对应有符号整数:int8,int16,int32,int64. 对应无符号整数:uint8,uint16,uint32,uint64. 计算最大数和最小

  • JavaScript数据类型的存储方法详解

    一个很基础的知识点,JavaScript中基本数据类型和引用数据类型是如何存储的. 由于自己是野生程序员,在刚开始学习程序设计的时候没有在意内存这些基础知识,导致后来在提到"什么什么是存在栈中的,栈中只是存了一个引用"这样的话时总是一脸懵逼.. 后来渐渐的了解了一些内存的知识,这部分还是非常有必要了解的. 基本数据结构 栈 栈,只允许在一段进行插入或者删除操作的线性表,是一种先进后出的数据结构. 堆 堆是基于散列算法的数据结构. 队列 队列是一种先进先出(FIFO)的数据结构. Jav

  • (MariaDB)MySQL数据类型和存储机制全面讲解

    1.1 数据类型概览 数据类型算是一种字段约束,它限制每个字段能存储什么样的数据.能存储多少数据.能存储的格式等.MySQL/MariaDB大致有5类数据类型,分别是:整形.浮点型.字符串类型.日期时间型以及特殊的ENUM和SET类型. 这5种数据类型的意义.限制和相关说明如下图所示: 各数据类型占用字节数,参见mariadb官方手册. 1.2 存储机制和操作方式 数据类型之所以能限定字段的数据存储长度,是因为在创建表时在内存中严格划定了地址空间,地址空间的长度是多少就能存储多少字节的数据.当然

  • C语言线程对象和线程存储的实现

    当每个线程为各自的变量使用全局标识符时,为保留这些变量各自的数据,可以采用线程对象(thread-local object)和线程存储(thread-specific storage). 这两项技术允许在一个给定线程中执行的函数可以共享数据而不造成冲突,即便当其他线程也在执行同样函数的情况下. 使用线程对象 线程对象是在声明中包含新存储类修饰符 _Thread_local 的全局或静态对象.这意味着:每一个线程拥有属于自己的线程对象实例,它在线程启动时创建并初始化.对象的存储周期等于线程的运行时

随机推荐