二、基本数据类型的表现形式

2.1 整数类型

       C++提供的整数数据类型有三种:int、long、short. 在 Microsoft Visual C++ 6.0中,int 类型与long类型在内存中都占4个字节,short类型在内存中占两个字节。

         内存中的数据采用十六进制数显示。一个字节由两个十六进制数组成,在进制转换中,一个十六进制数可用4个二进制数表示,每个二进制数表示1位,因此一个字节在内存中占8位。

         在c++中,整数类型分为有符号型与无符号型两种。有符号整数可用来表示负数与正数,而无符号整数只能表示正数。

2.1.1 无符号整数

          在内存中,无符号整数的所有位都用来表示数值。以无符号整型数据unsigned int为例,此类型的变量在内存中占4个字节,由8个十六进制数组成,取值范围为0x00000000~0xFFFFFFFF, 如果转换为十进制数,则表示为0~4294967295. 当无符号整型不足32位时,用0来填充剩余高位。 

2.1.2 有符号整数

     有符号整数中用来表示符号的是最高位--符号位。最高位为0表示正数,最高位为1表示负数。有符号整数在内存中同样占4字节,但由于最高位为符号位,不能用来表示数值,因此有符号整数的取值范围要比无符号整数取值范围少1位,即 0x80000000~ 0x7FFFFFFF, 如果转换为十进制,则表示范围为-2 147 483 648 ~ 2 147 483 647.

        在有符号整数中,正数表示区间为:0x00000000 ~ 0x7FFFFFFF ; 负数的表示区间为:0x80000000 ~ 0xFFFFFFFF

        负数在内存中都是以补码形式存在的,补码规则是用0减去这个数的绝对值,也可以简单地表示为对这个数取反加1.

2.2 浮点数类型

      C/C++中,使用浮点方式存储实数,用两种数据类型来保存浮点数:flaot(单精度)、double(双精度)。float在内存中占4字节空间,double在内存中占用8字节空间。

2.3 字符和字符串

    字符串是由多个字符按照一定排列顺序组成的,在C++,以‘\0’作为字符吕结束标记。每个字符都记录在一张表中,安们各自对应一个唯一编号,系统通过这些编号查找到对应的字符并显示。字符表格中的编号便是字符的编码格式。

2.4 布尔类型

     布尔类型是用于判断执行结果的数据类型,它的判断比较值只有两种情况:0与非0.

2.5 地址、指针和引用

    地址: 在C++中,地址标号使用十六进制表示。取一个变量的地址使用“&”符号,只有变量才存在内存地址,常量 没有地址(不包括const定义的伪常量)。例如,对于数字100,我们无法取出它的地址。

  指针:指针的定义使用“TYPE* ”, TYPE为数据类型,任何数据类型都可以定义指针 。指针本身也是一种数据类型,它用于保存各种数据类型在内存中的地址。指针变量同样可以取出地址,所以会出现多级指针。

   引用:引用的定义使用“TYPE&”, TYPE为数据类型。在c++中是不可以单独定义的,并且在定义时就要进行初始化。引用表示一个变量的别名,对它的任何操作,本质上都是在操作它所表示的变量。

2.5.1 指针和地址的区别

     在32位操作系统下,地址是一个由32位二进制数字组成的值。为为便于查看,转换成十六进制进行显示,用于标识内存编号。 指针是用于保存这个编号的一种变量类型,它包含在内存中,所以可以取出指针 类型变量在内存中的位置--地址。由于指针保存的数据都是地址,所以无论什么类型的指针都占据4字节的内存空间.

地址和指针

指针可以根据指针类型对地址对应的数据进行解释。而一个地址值无法单独解释数据,对于上图中0x0012FF68这个地址值,仅仅凭借它自己无法说明该地址处对应数据的信息。

2.5.2 各类型指针的工作方式

    在c++中,任何数据类型都有对应的指针类型。指针中保存的都是地址,为什么还需要类型作为修饰呢?因为需要用类型去解释这个地址中的数据。每种数据类型在内存中所占的内存空间不同,指针 中只保存了存放数据的首地址,而没有指明该在哪里结束。这时就需要根据对应的类型来寻找解释数据的结束地址。

2.5.3 引用

       引用类型在C++中被描述为变量的别名。实际上,c++为了简化指针操作,对指针的操作进行了封装,产生了引用类型。实际上引用类型就是指针类型,只不过它用于存放地址的内存空间对使用者而言是隐藏的。

2.6 常量 

     常量数据在程序运行前就已经存在,它们被编译到可执行文件中。当程序启动后,它们便会被加载进来 。这些数据通常都会在常量数据区中保存,该节区的属性中是没有可写权限的,所以对常量进行修改时,程序会报错。

常量数据的地址减去基地址,便是它在文件中的偏移地址。以下图中字符指针所保存的地址为例,这个地址为常量字符吕“Hello World!”的首地址。

常量字符串地址

常量字符串首地址为 0x00423FA8 ,该程序的基地址为 0x00400000,所以在文件对应的偏移地址为:字符串首地址-基地址 = 0x00023FA8 ,使用十六进制查看器打开该程序可执行文件找到对应数据:

常量字符串在文件中的位置

2.6.1 常量的定义

        在c++中,可以使用宏机制#define来定义常量 ,也可以使用const将变量定义为一个常量。#define定义的常量名称,编译器对其进行编译时,会将代码中的宏名称替换成对应信息。宏的使用可以增加代码的可读性。const是为了增加程序的健壮性而存在的。

2.6.2 #define和const的区别

      #define是一个真常量,而const却是由编译器判断实现的常量,是一个假常量 。在实际中,使用const定义的变量,最终还是一个变量,只是在编译器内进行了检查,发现有修改则报错。

      由于编译器在编译期间对const变量进行检查,因此被const修饰过的变量是可以修改的。利用指针获取到const修饰过的变量地址,强制将指针的const修饰去掉就可以修改对应的数据内存。

const int nConst =5;   

mov dword ptr [ebp-4], 5  

int *pConst = (int*)&nConst;

lea eax, [ebp - 4]

mov dword ptr [ebp-8], eax

*pConst = 6;

mov ecx,dword ptr [ebp - 8]

mov dword ptr [ecx],6

int nVar = nConst;

mov dword ptr [ebp-0ch],5

你可能感兴趣的:(二、基本数据类型的表现形式)