剖析数据在内存中的存储(C语言)

一、数据类型介绍

在C语言中内置数据类型有

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

在观察上述类型后,会发现并没有使用非常多的字符串所对应的类型,那么C语言中有字符串类型吗?

答案是:没有,C语言不存在显式的字符串类型,C语言中的字符串都以字符串常量的形式出现或存储在字符数组中

注:unsigned表示无符号数,signed表示有符号数,在一般创建变量时不声明为unsigned默认为signed,且signed可以省略不写,如:signed int ——>int,关于符号数类型下文会继续学习,此处认识到C语言中有哪些类型即可

//整形家族
short                        //2字节
unsigned short [int]
signed short [int]

int                          //4字节
unsigned int
signed int

long                         //4字节
unsigned long [int]
signed long [int]

char                        //1字节
unsigned char
signed char

在这里你可能会问char类型不是字符类型吗,怎么能算到整型家族,那是因为char类型在内存中存放时都是以ASCII码值得方式存放在内存中,而ASCII码值又是整型,所以算在整形家族

//浮点家族
float                        //4字节
double                       //8字节
//构造类型
数组类型      
结构体类型    struct
枚举类型      enum
联合类型      union
//指针类型                    //指针大小为4/8(32位/64位)
int *                        //指针+1(或-1)左(右)移动4个字节
char *                       //指针+1(或-1)左(右)移动1个字节
float *                      //指针+1(或-1)左(右)移动4个字节
void *                       //不可以对void*类型指针进行操作,因为无法确定其类型也不能进行解引用操作
//空类型
void通常表示空类型(无类型)通常用于函数参数、返回值、指针类型

二、整形在内存中的存储

我们知道,要创建一个变量,是需要在内存中占用空间的,而类型就是决定创建的变量占用多少字节的内存,但是这些数据是怎样放在内存中的呢?

接下来我们一起针对这个问题展开学习

首先我们都知道,计算机能能“听”懂的是二进制,也就0/1(低/高电平)来控制电流从而控制硬件的工作,所以我们先来对二进制进行简单的学习

(1.)二进制

在学习二进制之前,我们联系生活中的算数,我们经常会在运算中说到逢10进1,这里的逢10进1就是进制,意为当这一位权满10的时候向高位进1;

通过这个图我们对二进制有了简单的理解,那么我们继续学习,

在计算机中,整形有三种表示方式,:原码、反码、补码,三种表示方式均有数值位和符号位,其中0表示正、1表示负,数值位即为数子的数值

//原码
将其他进制的数字直接换算成二进制数即可
//反码
将原码的符号位取反即可,(在有符号二进制数中,最高位为符号位,其余均为数值)
//补码
将得到的补码+1即可,若想由补码再得出原码,1、按原码->反码->补码的相反顺序即可得出
                                      2、将补码取反再加1也可得出原码
//注意这里:同时正数的原、反、补码都是相同的!!!!

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

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

一处理;

同时,加法和减法也可以统一处理(CPU只有加法器)此外,补码与原码相互转换,其运算过程

是相同的,不需要额外的硬件电路,

在看完理论上的存放后,我们来看看实际中是什么样的,

通过上述图片我们可以看到变量a的地址上存放的是数值20,而

20的二进制数应该是 00000000 00000000 00000000 00010100(在这里补0是为了与计算机机器字长等长所补的,不影响数值的变化,仅看数值为10100)0x00000014,这是原数值直接对应的二进制,但是如图所示,是0x14000000.那么这么显示是什么原因呢?我们接着往下学习

此处补充2进制——>16进制

在进行二进制到16进制转换时,四位二进制转换为1位16进制数,因为1111d,即为15,而16进制数满16进

大端字节序、小端字节序

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

中;

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

址中

我自己的理解就是内存中排序顺序与你转换数字相同的是大端字节序,与你直接换算顺序相反为小端

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

小练习:请写出一个代码测试当前机器的大小端

#include<stdio.h>

int main()
{
    int i = 1;    //二进制为00 00 00 01
    char* p = &i; 
    if (*p == 1)//char*指针一次控制一个字节的内容那么如果是小端那么指向的第一个字节将会是01.也就是1
    {
        printf("小端\n");
    }
    else       //同理如果是大端则指向的第一个字节将会是00.也就是0
    {
        printf("大端\n");
    }
    return 0;
}
//代码2
int check_sys()//这个的思路与上一代码的思路是相同的
{
    union       //union是联合体,其成员共用同一块内存,那么整形i创建的值为1
    {           //当使用char类型的c读取时只能读取一个字节,那么取出的第一个字节将确定时大端还是小端
        int i;
        char c;
    }un;
    un.i = 1;
    return un.c;
}

三、浮点数在内存中的存储

浮点数与整形在内存中的存储是完全不同的,根据国际标准IEEE(电气和电子工程协会)754规定,任意一个二进制浮点数可以表示成如下形式:

(-1)^S * M * 2^E

(-1)^s表示符号位,当s=0,V为正数;当s=1,V为负数

M表示有效数字,大于等于1,小于2

2^E表示指数位

一些规定:(以短浮点数为例)

  1. E=0且M=0,则真值为0

  1. E=0且M!=0,则为非规格化数,真值为(-1)^s*0.M*2^-126 注意这里与上面是有去别的

  1. 1<=E<=254时,则为(-1)^s*0.M*2^E-1267

  1. E=255时且M=0,真值为正/负无穷

  1. E=255且M!=0,真值为'NaN'(非数值)

  • 5
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值