数据在内存中的存储及大小端问题(C语言)

本篇博客将重点介绍以下内容:

  1. 数据类型
  2. 整型在内存中的存储:原码,反码,补码
  3. 大小端字节序介绍及判断

1.数据类型详细介绍

C语言内置类型有:char(字符型 1字节) ,short(短整型 2字节), long(长整型 4字节),        long long(更长的整型  8字节 ), float(单精度浮点型  4字节), double(双精度浮点型  8字节) ;

字符型(char)在存储的时候,存储的是字符的ASCII码值,ASCII是整数

数据类型        无符号有符号
charunsigned  char signed    char 
shortunsigned shortsigned     short
int unsigned   intsigned     int
longunsigned long signed     long

有正负的数据可以存放在有符号的变量中,只有正数可以存放在无符号的变量中。

平常定义变量时:int a = 0;默认为  signed int 

有符号数,最高位为符号位,1表示负数,0表示正数。对于无符号数来说,最高位也是数据位

浮点数类型float ,  double,   long double

构造类型 (自定义类型)数组类型,结构体类型  (struct) ,枚举类型 (enum),联合类型 (union)

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

2.整型在内存中的存储

一个变量的创建是要在内存中开辟空间的,空间的大小是根据不同的类型而决定的

首先来了解一下原码,反码和补码,计算机中的整数有这三种表示方法 。原码:直接将数值按照正负数的形式翻译成二进制就行,正整数的原码,反码,补码一样

对于负整数,其补码与原码不同,得到补码的方法:先得到反码:符号位不变,其他位按位取反,再把反码加1即得到补码

举个例子:int a = -1;int 类型四个字节

    -1的原码:10000000  00000000  00000000  00000001

     -1的反码:1111 1111  1111 1111    1111 1111  1111 1110   //符号位不变,其他位按位取反

     -1的补码:1111 1111   1111 1111    1111 1111  1111 1111

计算 1+(-1),同样,不能直接用它们的原码计算,应该换成补码进行计算

1的补码与原码相同:     00000000 00000000 00000000 00000001

                -1的补码 :     1111  1111 1111 1111  1111 1111  1111 1111 

                        结果:    11111  1111 1111 1111  1111 1111  1111 1111 

                    最高位的1放不下丢失,所以最后结果为0;

 在计算机系统中,数值一律用补码来表示和存储,原因在于,使用补码,可以将符号位和数值域统一处理;同时,加法和减法也可以统一处理(CPU只有加法器)此外,补码与原码相互转换,其运算过程是相同的,不需要额外的硬件电路。

看看下面的题目:

 

 结果为:                                                                           

%u打印无符号数 , 变量ch 为无符号数,可是负数是不能存储在无符号变量中的

先写出-10的原码:10000000 00000000 00000000 00001010

           -10的反码: 1111 1111  1111 1111 1111 1111 1111 0101

           -10的补码:  1111 1111  1111 1111 1111 1111 1111 0110

整型在计算机中以补码形式存储,打印无符号数,最高位为数据位,相当于-10的补码存储的是一个正数,原码与-10补码相同

3.大小端介绍及判断

大小端字节序存储分为大端字节序存储小端字节序存储

例如:int a = 0x11223344;

用四个字节存放a的值,11 22  33  44,从低地址到高地址怎样存放呢?

大端字节序:把一个数据低位字节处的数据存放在高地址处,把高位字节处的数据存放在低地址处

小端字节序:把一个数据高位字节处的数据存放在低地址处,把低位字节处的数据存放在高地址处

例如:一个16bit 的short 类型a,在内存中的地址为0x0010,x的值为0x1122,那么0x11为高字节,0x22为低字节

对于大端模式,就将0x11放在低地址处,即0x0010中,0x22放在高地址处,即0x0011中,小端模式,刚好相反。我们常用的x86结构是小端模式,而KEIL C51则为大端模式,很多的ARM,DSP都为小端模式,有些ARM处理器还可以由硬件来选择是大端模式还是小端模式。 

那么,我们如何编写代码来判断目前使用的机器是大端还是小端呢

           

 最后,再看一题来加深理解

                                              

-1的补码:1111 1111   1111 1111   1111 1111 1111 1111

但是整型四个字节要存放在 char 类型的变量中,大小为一个字节,要发生截断,1111 1111

a,b同理截断后都为 1111 1111,%d最后打印的是整数,要发生整型提升,按照其类型来补,有符号数高位补符号位:

1111 1111   1111 1111   1111 1111 1111 1111   //补码

%d打印的是原码,要换成原码,减1先得到反码:1111 1111 1111 1111 1111 1111 1111 1110

原码:1000 0000 0000 0000 0000 0000 0000 0001

所以,a, b打印的结果都为 -1

c是无符号数整型提升直接补0:00000000 00000000 00000000 11111111补码为正数,正数的原码和补码相同,所以结果为255.

 

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值