c语言 数据存储与原码 反码 补码详细解析

目录
  • 前言
  • 1.数据的类型介绍
    • 1.1整形家族
  • 2.整形在数据内存中的存储
    • 2.1 原码 反码和补码(三种整型数的表示方法)
    • 2.2大小端字节序序的介绍
    • 2.3 练习
  • 3.浮点型在内存中的存储
    • 3.1 先举一个例子
    • 3.2 浮点数储存的规则

前言

学习本章你会了解:

1.数据类型详细介绍

2.整形在内存中的存储:以及了解原码、补码、反码

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

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

1.数据的类型介绍

在学习数据储存之前,让我们先认识一下数据类型。以下这些数据类型是我们初学c语言时的基础类型以及大小所占字节数。

比如 所占字节数 类型
char 1 //符数据的类型
shot 2 //短整型
int 4 //整形
long (规定sizeof(long)>=sizeof(int) ) 4 //长整型
long long(部分编译器不支持) 8 //更长的起整数
float 4 //单精度浮点数
double 8 //双精度浮点数

还有构造类型:

数组类型

结构体类型struct

枚举类型enum

联合类型union

指针类型:

int* pa;

char* pb;

float* pc;

void* pd;

除了以上类型,实际上还有布尔类型:_Bool(专门用来表示真假的类型)

举个栗子(在c99中可用)

#include<stdio.h>
#include<stdbool>
main()
{
_bool flag=true;
if(flat)
printf("hello world")
return 0;
}              //结果就会打印一个hello world

1.1整形家族

整形家族中包括int short long,还有char。

char也是整形家族中的吗?

答案是:是的,因为char对应的字符的ascii码值中,字符对应的就是整形。

在这些整形类型之中,还可以分为无符号整形和有符号整型:

int=signed int

short=signed short

long=signed long

那是否char 等于 signed char呢

结果又跟其他整形家族中的成员不同,在标准情况下char不是等于sign char~(但是在常规编译器中是相等的)。

2.整形在数据内存中的存储

我们知道变量创建就是开辟空间,开辟空间的大小由数据的类型来决定。

那么数据在所在的空间是怎样储存的呢?

在vs2019中输入:

int    a=20;
int    b=-10;

就代表在内存中开辟四个字节的空间

其中14 00 00 00 就是a十六进制对应反码的值

和前面相同,f6 ff ff ff就是b十六进制对应反码的值

我们都知道计算机都是以二进制来存储信息,那为什么在内存图中看到的是十六进制呢?

这仅仅是便于观察,当以十六进制储存时,有没有感到反码有点长呢,如果换成二进制就更不宜观察了,故规定以十六进制来保存。

提到这里,什么是反码呢?为什么又反码的出现呢?

2.1 原码 反码和补码(三种整型数的表示方法)

原码:原码就是数字对应二进制的表示方法,其中最后一位数字是符号位,表示正负的,

而小字节序就是二进制对应的是数。

如a的原码是:0000 0000 0000 0000 0000 1010

反码:反码的数值就是在原码的基础之上进行转换过来的,当数值为正数时,反码的数据大小跟原码相同,当数值是负数是,其反码的值就是在原码的基础上,除了符号位,其他位都是按位取反。

补码:补码数值为正数时,其值大小就是原码,为负时,其值的大小就是在反码的基础之上,在进行加一。

原码得到补码取反加一即可,其实补码得到原码也是取反加一(感兴趣的可以试试)

举个栗子:

a的原码 反码 补码

原:0000 0000 0000 0000 0001 0100

反:0000 0000 0000 0000 0001 0100

补:0000 0000 0000 0000 0001 0100

b的原码 反码 补码

原:1000 0000 0000 0000 0000 1010

反:1111 1111   1111  1111  1111  0101

补:1111 1111  1111   1111   1111  0110

那我们系统会出现原码反码和补码三种表示方法呢,一种表示方法不行吗?

我们能想到的,科学家也能想到,但一种表示方法有缺陷。

就比如说:当计算1+(-1)的时候(计算机只能实现加法的运算)

统一用原码的结果是

0000 0000 0000 0000  0000 0001

1000 0000 0000 0000 0000  0001

结果是1000 0000 0000 0000 0000  0010

用补码计算的结果是:

0000 0000 0000 0000 0000  0001

0111  1111  1111 1111  1111  1111

结果是1000 0000 0000 0000 0000 0000 也就是0

你是不是瞬间知道为什么要三种表示方法,为什么有补码的存在了

有没有get到科学家的伟大之处

2.2大小端字节序序的介绍

大小端字节序分别是哪一种?

a在内存中的数值44 33 22 11就是小端字节序

那大端字节序就是11 22 33 44

大小端字节序的定义是什么?

大端字节序:当一个数的低字节序放在高地址处,或者高字节序的放在低地址处时,就是我们所说的大端字节序。

小端字节序:当一个数的高字节序放在低地址处,或者低字节序的放在高地址处时,就是我们所说的小端字节序。

放在倒着就是小端字节序,记住它即可。

为什么数据要分大小端字节序呢?

大小端字节序来源于于乔纳森·斯威夫特的小说《格列佛游记》,这是因为在计算机系统中,我们都是以字节为单位的,每个地址单元都对应着一个字节,一个字节为8bit,但是在c语言中除了8bit的char之外,还有16bit的short型,32bit的long型(看具体编译器),另外,对于位数大于8位的处理器,例外16位的或者32位的处理器,由于寄存器宽度大于一个字节,那么必然存在着一个如何将多个字节序排序的问题。因此就导致了大端存储模式,和小端存储模式。

那么怎么判断大小端字节序呢?

下面由一个例题来讲解:(这是百度2015年系统工程师的笔试题)

用代码来判断系统大小端字节序:

int a;

char*pa=(char*)&a;

if(*pa==1)

printf("小端字节序“);

else

printf(“大端字节序”);

2.3 练习

题一:

//输出结果是什么
#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
}

输出的结果分别是-1 -1 255

前面两个很容易理解 signed char与char意思都是有符号的整数,所以打印的结果都是-1.

都是对于无符号来说这时候就要进行整形提升了

当char型以整形来打印时过程如下:

原码:10000001

反码:11111110

补码:11111111

unsigned整形提升后:0000 0000 0000 0000 1111 1111

这是的补码同样也是: 0000 0000 0000 0000 1111 1111

就是最终c的值。

题二:

​#include<stdio.h>

int main()
{
char a=-128;
printf(%u\n",a);  //u就是以无符号的类型打印出来
return 0;
}

-128的原码: 1000 0000 0000 0000 1000 0000

反码1111 1111 1111 1111 0111 1111

补码1111  1111 1111 1111 1000 0000

因为是char型 补码提取后:10000000

正进行整形提升,因为char是无符号整形,所以提升后:

1111 1111 1111 1111 1000 0000

再以无符号整形形式打印后原反补相同即:1111 1111 1111 1111 1000 0000

再转化成十进制:4294967169

运行证明以如下

数据的范围是多少呢?unsigned char与char存放的数据是否相等呢?

事实证明char与unsigned char数据范围并不一样

char的整形数据范围是-128~127,而unsigned char的范围是0~255;

(short 与unsigned short的整形取值范围也不一样

short的整形数据范围是-32768~32767,而unsigned short能存储的数据范围则是0~65535

3.浮点型在内存中的存储

首先列出一个常见浮点数表示方法:

1E10 可能你并不知道这是什么意思;

实际上他的意思是1.0*10^10;

3.1 先举一个例子

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

n的值为:9

*pFloat的值为:0.00

num的值为:1091567616

*pFloat的值为:9.000000

这个结果是否跟你想的一样呢?

其实n的值与最后一个*pFloat的值可能我们很容易知道(也可能是猜的 哈哈)

在求解这道题之前让我们先了解这个题的知识吧~

3.2 浮点数储存的规则

IEEE(电气和电子工程协会754标准)标准规定:

任何二进制的浮点数都可以以这种标准表示出来:

基本公式是:(-1)^S*M*2^E;(这里的E是无符号类型)

其中M是有效数子,E是指数,S用来表示正负;

举个栗子:

5.5——10进制的表示

转化为二进制的结果是:101.1;

用公式表示为:(-1)^0 (1.011)*2^2    此时S=0,M=1.011,E=2;

对于64位浮点数,最高位1位是符号位s,接着是11位是指数E, 剩下的52位是有效数字。

如果E为八位,他的取值范围0~255,如果E为11为,他的取值范围0~2047;

有两个极限

当E为0时,此时的真实的E为1-127=-126;此时的数值根据公式,也就是无限接近与0;

当E为254时,此时的真实的E为254-127=127;此时的数值根据公式,也就是无穷大。

说到这里,你可能有一点疑惑,为什么都要减一个127,这是因为避免出现E为负数的情况(因为这里的E是无符号整形),在真实的E的基础上加了127,所以为了得到求出真实的E,就需要减去一个127.

现在回到原来的题目之上

0000 0000 0000 0000 0000 0000 0000 1001--九的原码反码与补码。

这里的0 是 s;00000000为E;0000000000000000001001为m

此时(-1)^0*0.00000001*10*2^(-126)

由于float默认只打印小数点后六位,所以最终打印0.000000;

九的转化位二进制:1.001;

1.001*2^3

=0 M=1.001 E=3;

0100 0001 0001 0000 0000 0000 0000 0000

再以整形的形式打印的话,此时的值就是0100 0001 0001 0000 0000 0000 0000 0000就是num的补码,由于符号位是0,所以最终的原码等于补码。也就是1091567616

如果以浮点型打印的话也就是9.000000

结语:

写的很长时间,如果有用就收藏吧

到此这篇关于c语言 数据存储与原码 反码 补码详细解析的文章就介绍到这了,更多相关c语言 数据存储内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • C语言数据存储详解

    目录 一.数据类型 二.整型在内存中的存储 1.原码.反码.补码 大小端介绍 三.浮点型在内存中的存储 1.举一个浮点数存储的例子: 2.浮点数存储规则: 总结 一.数据类型 char:字符数字类型.有无符号取决于编译器,大部分编译器有符号(signed char) 而short.int.long都是有符号的. unsigned char c1=255;内存中存放二进制的补码:11111111 都是有效位,没有符号位 char c2=255;结果为-1 同理可推出short.int等 二.整型在

  • C语言 数据存储方式知识点详解

    C语言 数据存储方式 一.源码 一个数的原码(原始的二进制码)有如下特点: 最高位做为符号位,0表示正,为1表示负 其它数值部分就是数值本身绝对值的二进制数 负数的原码是在其绝对值的基础上,最高位变为1 下面数值以1字节的大小描述: 十进制数 原码 +15 0000 1111 -15 1000 1111 +0 0000 0000 -0 1000 0000 注:原码表示法简单易懂,与带符号数本身转换方便,只要符号还原即可,但当两个正数相减或不同符号数相加时,必须比较两个数哪个绝对值大,才能决定谁减

  • C语言基础 原码、反码、补码和移码详解

     原码.反码.补码.移码的作用? 在计算机内,机器数有无符号和带符号数之分.无符号数表示正数,在机器数中没有符号位.位于无符号数,若约定小数点的位置在机器数的最低位之后,则是纯整数:若约定小数点的位置在机器数的最高位之前,则是纯小数.对于带符号数,机器数的最高位是表示正.负的符号位,其余位则表示数值.若约定小数点的位置在机器数的最低数值位之后,则是纯整数:若约定小数点的位置在机器数的最高数值位之前(符号位之后),则是纯小数. 为了便于运算,带符号位的机器数可采用原码.反码和补码等不同的编码方法,

  • c语言 数据存储与原码 反码 补码详细解析

    目录 前言 1.数据的类型介绍 1.1整形家族 2.整形在数据内存中的存储 2.1 原码 反码和补码(三种整型数的表示方法) 2.2大小端字节序序的介绍 2.3 练习 3.浮点型在内存中的存储 3.1 先举一个例子 3.2 浮点数储存的规则 前言 学习本章你会了解: 1.数据类型详细介绍 2.整形在内存中的存储:以及了解原码.补码.反码 3.大小端字节序的介绍和判断 4.浮点型在内存中的存储解析 1.数据的类型介绍 在学习数据储存之前,让我们先认识一下数据类型.以下这些数据类型是我们初学c语言时

  • 原码, 反码与补码基础知识详细介绍

    原码, 反码,补码详解 本篇文章讲解了计算机的原码, 反码和补码. 并且进行了深入探求了为何要使用反码和补码, 以及更进一步的论证了为何可以用反码, 补码的加法计算原码的减法. 论证部分如有不对的地方请各位牛人帮忙指正! 希望本文对大家学习计算机基础有所帮助! 一. 机器数和真值 在学习原码, 反码和补码之前, 需要先了解机器数和真值的概念. 1.机器数 一个数在计算机中的二进制表示形式,  叫做这个数的机器数.机器数是带符号的,在计算机用一个数的最高位存放符号, 正数为0, 负数为1. 比如,

  • C语言数据存储归类介绍

    目录 数据类型的介绍 类型的基本归类 整型在内存中的存储 什么是大小端 浮点数在内存中的存储 浮点数在内存中的存储规则 数据类型的介绍 在前面的章节中我们基本认识到了各种数据类型,这里我们就稍微回忆以下吧 类型的意义: 决定了访问内存空间的大小 决定了看待内存空间的视角(例如:整型和字符数据类型) 类型的基本归类 整型家族: char    unsigned char    signed charshort    unsigned short [int]    signed short [int

  • C语言main函数的参数及其返回值详细解析

    返回值的作用 main函数的返回值用于说明程序的退出状态.如果返回0,则代表程序正常退出:返回其它数字的含义则由系统决定.通常,返回非零代表程序异常退出.下面我们在winxp环境下做一个小实验.首先编译下面的程序:int main( void ){    return 0;}然后打开附件里的"命令提示符",在命令行里运行刚才编译好的可执行文件,然后输入"echo%ERRORLEVEL%",回车,就可以看到程序的返回值为0.假设刚才编译好的文件是a.exe,如果输入&

  • C语言数据的存储超详细讲解下篇浮点型在内存中的存取

    目录 前言 浮点型在内存中的存储 浮点数存储的例子 浮点数存储规则 IEEE 754规定 IEEE 754对有效数字M的特别规定 IEEE 754对指数E的特别规定 存入内存是E的规定 从内存取出时E的规定 举例 1 举例 2 举例 3 判断两个浮点数是否相等? 总结 前言 本文接着学习数据的存储相关的内容,主要学习浮点型数在内存中的存储与取出. 浮点型在内存中的存储 常见的浮点数:3.14159.1E10 浮点数家族包括: float.double.long double 类型 浮点数表示的范

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

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

  • C语言数据在内存中的存储流程深入分析

    目录 前言 类型的基本分类 整型 浮点数 自定义类型 整型在内存中的存储 原码.反码.补码 大端和小端 如何判断编译器是大端还是小端 浮点数在内存中的存储 总结 前言 C语言中有char.short.int.long.long long.float和doubole这些数据类型.这些数据类型也叫内置类型. 所占存储空间的大小: 数据类型 所占存储空间的大小 char 1个字节 int 4个字节 short 4个字节 long 4个字节 long long 32位平台下占4个字节 ,64位平台下占8

  • C语言数据(整数、浮点数)在内存中的存储

    本篇主要讨论:整数.浮点数在内存中是怎么保存的! 数据类型详细介绍 在前面C语言基础概览中,已经提到过了基本的C语言内置类型,但C语言的数据类型有无数种~ 但是可以把这些类型分为几个大类: 类型的归类: 存整数的 char,short,int,long,long long及所配套的unsigned,int*,int[]- 2.存浮点数的 float,double,float[]- 结构体(结构体在内存中的存储后面在进行讨论~) 整数在内存种的存储: 1.字节序 2.补码 内存窗口 调试模式下的内

随机推荐