说明:比较简单,水平也很一般,错误难免,欢迎批评指正,谢谢
C语言之基本数据类型变量
基本数据类型
先看下C语言的基本数据类型:
bool 布尔 1字节
char 字符型 1字节
int 整型 4字节
float 浮点型(单精度) 4字节
double 浮点型(双精度) 8字节
数据类型是用来描述对应表示的数据的相关属性,如:大小(在内存中占几字节),数值表示的形式(0,1,有符号是没…)。
看下各种数据类型的具体表示,这里不得不提到一个东西,就是变量。
先看示例代码:
代码:
int _tmain(int argc, _TCHAR* argv[]) { //bool bool isTest = true; //char char cChar = 'T'; //int int nNum = 0x123; //float(double) float fValue = 1.2f; //double double dfValue = 1.2; return 0; }
代码:
//boolbool isTest = true;
bool型的值只有true和false,内存中值为1和0,实际上除了为0的情况是false,其他都为true,比如下面的情况。
代码:
isTest = 123; isTest = 0.2; isTest = 'a';
0x001DFCF3 01 cc cc cc cc 48 fd 1d 00 b8 25 09 01 01 00 00
代码:
//char char cChar = 'T';
在内存的表现形式如下,占1字节,16进制表示
0x001DFCE7 54 cc cc cc cc cc cc cc cc cc cc cc 01 cc cc cc T
表示的数据性质呈现一个环形的特性,一直+++或一直---总能回到原点,就跟地球是圆的一样(貌似没人说是方的了)
代码:
//char型 char cChar = 0x4; for (; ; ++cChar) //增加方向0x5,0x6,0x7---> { printf("%02X\r\n", cChar); if (cChar == 0x3) { printf("我又回来啦!\r\n"); break; } }
代码:
FFFFFFFE FFFFFFFF 00 01 02 03 我又回来啦! char cChar = 0x4; unsigned char cChar = 0x4;(无符号) FD FE FF 00 01 02 03 我又回来啦!
代码:
//int int nNum = 0x123;
0x001DFCD8 23 01 00 00 cc cc cc cc cc cc cc cc cc cc cc 54
这里采用小端(小尾)的存储方式,也就是地位在低地址,高位在高地址
0x00000123 从低到高地址为0x1DFCD8-0x1DFCDB对应存放 23 01 00 00
另外一种是大端(大尾)的存储方式,主要是就高低位方向相反,看下示例
在不同的硬件环境下对数据的处理会存在差异,内存中数据主要就是大小尾的问题。
比如数值0x12
在小尾存储方式的内存为12 00 00 00,->小尾读(0x12), 大尾读(0x12000000)
而在大尾方式下为 00 00 00 12 ->小尾读(0x12000000), 大尾读(0x12)
代码:
[B]//float(double)[/B ]float fValue = 1.2f; 0x001DFCB4 9a 99 99 3f cc cc cc cc cc cc cc cc 02 00 00 00 //double double dfValue = 1.2; 0x001DFCA4 33 33 33 33 33 33 f3 3f cc cc cc cc cc cc cc cc
大概的编码形式为:[指数位][指数][小数位]
直接操作栈地址
看下代码中的数值在内存中的分布情况:
代码:
int _tmain(int argc, _TCHAR* argv[]) { int nNum1 = 0x1; int nNum2 = 0x2; int nNum3 = 0x3; int nNum4 = 0x4; int nNum5 = 0x5; return 0; }
代码:
+ &nNum1 0x0016f748 int * + &nNum2 0x0016f73c int * + &nNum3 0x0016f730 int * + &nNum4 0x0016f724 int * + &nNum5 0x0016f718 int * &nNum1-&nNum5 12 unsigned long 0x0021F874 05 00 00 00 cc cc cc cc cc cc cc cc ....???????? 0x0021F880 04 00 00 00 cc cc cc cc cc cc cc cc ....???????? 0x0021F88C 03 00 00 00 cc cc cc cc cc cc cc cc ....???????? 0x0021F898 02 00 00 00 cc cc cc cc cc cc cc cc ....???????? 0x0021F8A4 01 00 00 00 cc cc cc cc fc f8 21 00 ....??????!.
局部变量是放在栈中,栈就是一块内存,栈的特性是先进后出,跟正常穿衣脱衣顺序类似,这里只要了解下即可。
1+2 的计算,其实就是拿对应内存的值来做加法运算
代码:
nNum5 = *(int*)0x0021F8A4 + *(int*)0x0021F898 ; 这里主要了解下就好,其实是指针的操作 *(类型*)内存地址 ->操作指定地址按指定类型使用 00CC1041 mov eax,dword ptr ds:[0021F8A4h] 00CC1046 add eax,dword ptr ds:[21F898h] 00CC104C mov dword ptr [nNum5],eax
0x0021F874 03 00 00 00 cc cc cc cc cc cc cc cc ....????????
0x0021F880 04 00 00 00 cc cc cc cc cc cc cc cc ....????????
0x0021F88C 03 00 00 00 cc cc cc cc cc cc cc cc ....????????
0x0021F898 02 00 00 00 cc cc cc cc cc cc cc cc ....????????
0x0021F8A4 01 00 00 00 cc cc cc cc fc f8 21 00
在来个复杂的运算 (因为VC2008占地址不固定每次都是动态取值,分布还是比较固定的说)
[code](1+2)*3+4
nNum5 = (*(int*)0x0018fa1c + *(int*)0x0018fa10)* *(int*)0x0018fa04 + *(int*)0x0018f9f8 ;
00FF1041 mov eax,dword ptr ds:[0018FA1Ch]
00FF1046 add eax,dword ptr ds:[18FA10h]
00FF104C imul eax,dword ptr ds:[18FA04h]
00FF1053 add eax,dword ptr ds:[18F9F8h]
00FF1059 mov dword ptr [nNum5],eax
运行后内存 (1+2)*3 + 4 => 3*3+4 => (13)10 (D)16
0x0018F9EC 0d 00 00 00 cc cc cc cc cc cc cc cc ....????????
0x0018F9F8 04 00 00 00 cc cc cc cc cc cc cc cc ....????????
0x0018FA04 03 00 00 00 cc cc cc cc cc cc cc cc ....????????
0x0018FA10 02 00 00 00 cc cc cc cc cc cc cc cc ....????????
0x0018FA1C 01 00 00 00 cc cc cc cc 74 fa 18 00 ....????t?..
[/code]
再来点有难度
(((1+2*3)^2+3*4-2)*3/2+3-4)*4
这个也没问题,就是地址操作嘛。。。。。。
ZZZ 不过写的也太累了,要是再复杂点,地址成百上千的不用运算,我晕了。
主角闪亮登场”变量,变量名”
变量,字面理解就是会变化的值。
变量名,字面理解就是会变化值的名字,你可以和前面的地址对应起来了嘛?
变量名要使用字面,_,数字做为名称,数字不能第一个(不然谁搞的清是数字还是变量),不能使用保留字,名字最好能望名知意。
我们再用变量名来做下运算
代码:
1+2 => nNum1+ nNum2 nNum5 = nNum1 + nNum2; 00CE1EE1 mov eax,dword ptr [nNum1] 00CE1EE4 add eax,dword ptr [nNum2] 00CE1EE7 mov dword ptr [nNum5],eax
代码:
00CC1041 mov eax,dword ptr ds:[0021F8A4h] 00CC1046 add eax,dword ptr ds:[21F898h] 00CC104C mov dword ptr [nNum5],eax
这个可提供了非常大的便利,从此就脱离的低级趣味了,可以定义一堆喜欢的名字
Int a;
Int aa;
Int aaa;
Int aaaa;
。。。。。。。。。。。。
莫非又穿越了,跟记数字有区别嘛,好的名字成功的开始
变量名的规范,个人习惯仅供参数
bool 型 is_xxx
int型 n_xxxx
char cXxxxx
float fXxxxx
DWORD dwXxxx
全局 g_类型+名称 g_nNumber
静态 s_类型+名字
成员 m_类型+名字 m_xXxxx
。。。。。。。。
总结:
1) 数据类型是用来约束所标识的类型的数据特性;
2) 在内存中数据都是16进制补码的形式存在,存在大小端的情况;
3) 浮点数采用IEEE的编码方式保存;
4) 变量名是对对应内存地址的一个别名,高级语言提高的一个友好的描述;
5) 变量名称要能反映数据类型和作用,避免穿越。
6) 内存中的数据和类型关联就有了相应的类型特性,也就是说通过指针方式来重新指定某地址的数据类型,说它是啥就是啥。OY!
有名称代号了就好办事了,9527给哥买张火车票去。哈哈!
说明:水平有限,错误不妥难免,欢迎批评指点,谢谢!
五边形 2011年5月
下一篇 关于常量链接:
http://bbs.pediy.com/showthread.php?p=963240#post963240