C语言的整形变量是如何用来存储整数的?

//二进制:1010101(C语言并没有单独的二进制表示方法。前面这个数表示十进制) //十六进制好处,可以直接观察这个数在内存中每个字节的内容 //负数的补码:负数的绝对值的原码取反加一 //负数的原码:负数的补码取反加一得到负数绝对值的原码,高位变为1 //低位优先:低位首先存在低地址 //高位优先:高位首先存在高地址

都知道第一位表示的是正负符号 则:表示的是0; 表示的是127,这样正数0-127就表示完了。轮到表示负数了,负数第一位为1(规定的) 则:表示的是-表示的是-127,这样负数就有-1到-127发现负数好像还有一个,表示0?正数已经有了,那就表示-128吧,不浪费。你把

原码就是符号位加上真值的绝对值, 即用第一位表示符号, 其余位表示值. 比如如果是8位二进制: 负数的反码是在其原码的基础上, 符号位不变,其余各个位取反. 负数的补码是在其原码的基础上, 符号位不变, 其余各位取反, 最后+1. (即在反码的基础上+1) 为了解决原码做减法的问题, 出现了反码: 计算十进制的表达式: 1-1=0 发现用反码计算减法, 结果的真值部分是正确的. 而唯一的问题其实就出现在"0"这个特殊的数值上. 虽然人们理解上+0和-0是一样的, 但是0带符号是没有任何意义的. 而且会有[]原和[]原两个编码表示0. 于是补码的出现, 解决了0的符号以及两个编码的问题: 这样0用[]表示, 而以前出现问题的-0则不存在了.而且可以用[]表示-128: -1-127的结果应该是-128, 在用补码运算的结果中, []补 就是-128. 但是注意因为实际上是使用以前的-0的补码来表示-128, 所以-128并没有原码和反码表示.(对-128的补码表示[]补算出来的原码是[]原, 这是不正确的) 使用补码, 不仅仅修复了0的符号以及存在两个编码的问题, 而且还能够多表示一个最低数. 这就是为什么8位二进制, 使用原码或反码表示的范围为[-127, +127], 而使用补码表示的范围为[-128, 127]. 因为机器使用补码, 所以对于编程中常用到的32位int类型, 可以表示范围是: [-2^31, 23^1-1] 因为第一位表示的是符号位.而使用补码表示时又可以多保存一个最小值.

3.1:浮点数定义和存储

C语言中浮点数的定义:
1. 单精度浮点数:float,4个字节
2. 双精度浮点数:double,8个字节

浮点数是将特定长度的连续字节(4个字节和8个字节)的所有二进制位(32位和64位)分割为特定宽度的三个域:

  1. 符号域:S,占1位,正数为0,负数为1
  2. 阶码域:E,占8位或者11位,E=e+127(float) or e+1023(double),指数e 有正负既有符号数,但阶码为正即无符号数,所以将e加上127或者1023作为偏移,方便指数的比较。
  3. 尾数域:M,占23位或者52位
  4. 计算浮点数的存储方式,只需要依次求出1位符号位,8位或11位的阶码,以及23位或者52位的尾数即可。

浮点数在X86系统以低位优先方式处处

C语言是一个强类型语言,数据必须明确指定类型。
char c = 'a';//'a'是字符常量,c是字符常量。常量是用单引号包围。

内建型别:数据以字节为单位存储在内存中

大写A的ASCII值为65,小写a的ASCII值为97,相差32。在程序中是个硬编码,不要使用,用'a'-'A'替代

网页通常采用Utf-8编码,可以加快浏览速度。

C语言中的类型,可以通过typedef定义成新的类型。比如下面的例子:

4.2:类型长度与取值范围

sizeof计算类型或者变量的长度,字节为单位,是操作符,不是函数。在编译阶段确定,而不是运行阶段。

有符号最小值:除了1之外,其他位都为0

  1. 类型转换:将一种类型转换为另一种类型,一种类型指针转为另一种类型指针。
  2. 强制转换:(新类型)变量

上面的转换都是从宽度短的转换为宽度大的。当把一个宽度短的数据类型到宽度大的数据类型转换的时候,是用符号位填充多出的位数。


下面的例子是把宽度长的转换为宽度短的,这个过程可能会造成数据的丢失:

当把占4个字节的x强转为占2个字节的y的时候,整数的高位2个字节将会被截断因此,y只保留了0x中的低位2个字节0x5678。



如果一个运算符两边的运算数类型不同,先要将其转换为相同的类型,即较低类型转换为较高类型,然后再参加运算,转换规则如图所示。

常量,顾名思义,就是其值不会改变的数据,就是不同数据类型中不变的值。

变量,内存或寄存器中用一个标识符命名的存储单元,可以用来存储一个特定类型的数据,并且数据的值在程序运行过程中可以进行修改。

5.1:变量定义与命名

程序员一旦定义了变量,那么,变量就至少可为我们提供两个信息:一是变量的地址,即就是,操作系统为变量在内存中分配的若干内存的首地址;二是变量的值,也就是,变量在内存中所分配的那些内存单元中所存放的数据。

由于程序的多样需要,我们对变量也有各种各样的要求,比如:

C语言设置了以下变量:

  1. 静态变量:静态全局变量和静态局部变量;关键词:static
  2. 寄存器变量:关键词:register;
  3. 外部变量:关键词:extern;

在函数内部说明的变量为局部变量,只有在函数执行时,局部变量才存在,当函数执行完退出后,局部变量随之消失。也就是,当函数执行完退出后,原先在函数内定义的变量现在不能用。

与局部变量不同,全局变量在整个程序都是可见的,可在整个程序运行过程中,对于任何一个程序都是可用的。全局变量的说明的位置在所有函数之外,但可被任何一个函数使用,读取或者写入。

静态变量是分配在存储器中C程序所占据的数据段内,C程序运行的整个过程中一直保留,不会被别的变量占用。静态变量可以定义成全局变量或局部变量,当定义为全局变量时,在它定义的程序的整个运行期间均存在并且保持原来的存储单元位置不会改变

同静态全局变量定义一样,当在局部变量名前加静态变量说明符static,该变量就定义为静态局部变量。编译器为该变量建立永久存储单元。永久是指C程序运行的整个过程中一直保留,不会被别的变量占用。静态局部变量和静态全局变量的根本区别在作用区域上,静态局部变量只在它被说明的函数或复合语句中有效,并且在两次函数调用期间仍然保存其值不变,即就是有记忆功能;它们的生命期是相同的,和C程序整个运行期同在。

5.2:变量作用域存储空间生命周期

变量的作用域:变量能够在什么地方被访问。

变量的存储空间:存放变量的内存位置。要明白变量在内存中存放的位置,首先就先了解下系统的内存布局。

以x86为例,x86支持32位寻址,因此可以支持最大232=4GB的虚拟内存空间(也可以通过PAE技术增加到36位寻址,因此可以将寻址空间扩大到64GB)。如图所示,在4G的虚拟地址空间中,Windows系统的内存主要分为内核空间和应用层空间上下两部分,每部分各占约2GB,其中还包括了一个64KB的NULL空间以及非法区域。Windows内存的逻辑地址包含2部分,即段选择符和偏移地址,CPU在做地址翻译的时候,通过分段机制计算出一个线性地址,再通过页表机制映射到物理地址以便存取物理内存中的数据和指令。

X64(AMD64)的内存布局与X86的内存布局类似,不同的地方在于各自空间的范围和大小不同,同时X64下还存在着一些空洞(hole),如图所示。在X64内存理论上支持最大264的寻址空间,但实际上这个空间太大了,目前根本用不完,因此实际上的X64系统一般都只支持到40多位(比如Windows支持44位最大寻址空间为16TB,Linux 支持48位最大寻址空间256TB等),支持的空间达到了TB级别。但是,无论是在内核空间还是在应用层空间,这些上TB的空间并不都是可用的,存在着所谓的空洞。


一个进程的内存空间布局

Windows应用栈默认1M,可以用编译指令/stack可以改设其他值;

当程序加载入内存后,程序在内存中可以分为若干个区,这些区包括:静态区(.data,.rdata,.bss段等),代码区(.text),堆区,栈区等。

这个存放代码的,用汇编角度来看就是指令。
存放常量,字符常量,const常量。(read不可修改)
存放已经初始化好的全局变量和静态变量。
存放未初始化的全局变量和静态变量。
存放局部变量等。栈区存放着函数调用过程中的形参,返回地址以及局部变量等。

.rdata,.data,.bss都是存放的数据。除了.bss段,.rdata,.data段的值都是在编译的时候就确定了,并且将其编译进了可执行文件,经过反汇编都能找得到。bss段是在代码运行的时候手动编写汇编代码将其初始化为0的(这就是未初始化的全局和静态变量默认值为0的根源)


变量的生命周期变量有效的时间段,只有在变量的生命周期内,才能访问该变量。有的变量的生命周期是函数运行期间,函数结束,变量就消失了。有的变量的生命周期是程序运行期间,只要程序还未结束,变量就不会消失或销毁。

变量分类:全局变量,局部变量,静态变量(静态全局变量和静态局部变量),寄存器变量,外部变量。

静态区(.data存放初始化全局变量,.bss存放未初始化全局变量)
静态区(.data存放初始化全局变量,.bss存放未初始化全局变量)
当前函数内部,只初始化一次

寄存器变量:不像其他变量那样在内存中存放数据,而是在CPU的寄存器中暂存数据,使用寄存器变量比使用内存变量的操作速度快得多。只有整型和字符型变量可定义为寄存器变量。由于CPU中寄存器有限,尽量减少使用数量和和占用时间,用完马上释放;不能定义为全局变量,也不能定义在结构或者类中。

extern关键字:为了解决全局变量和函数的共用问题,就引入了 extern关键字。这样只需在一个文件中定义全局变量和函数,在另一个文件中要用到这些变量和函数时,只需将那个文件中的变量和函数说明表复制过来,在前面加上extern,告诉编译器,这些变量和函数已经在别的文件中定义说明。


我要回帖

更多关于 c语言中整型数据的存储形式 的文章

 

随机推荐