一个宏定义引发的问题
问题1:对与buffer宏定义的理解
一些得到的基本结论:int型数据占有一个字的空间,char型数据占有一个字节的空间,并且char数据类型的定义是为ASCII字符表量身定制的
对与buffer的理解:
#define buffer ((char*) * (int far*)0x200)
首先,复习对与基本宏定义的知识:对于# define pi (3.14)即pi = 3.14,在此我们首先应该认识到,最外面的括号仅仅是一个结构,来说明里面的内容是一个整体。
下面来研究buffer究竟是什么:
基本出发点:
通过研究buffer[10] = 0;这个语句的汇编结构来认识buffer是什么
图1
通过汇编语句,我们发现,首先,我们的将偏移地址0x200变成了0x0000 0200.并不是我们想当然认为的ds:0200
于是,我们首先对(int far *)0x200进行一个详细深入解读:
1.*首先赋予了0x200这个数地址的含义
2.()表明要对后面的数据进行强制性转换,但是转换成多少位?
3 far则表明了要将后面的数据进行4位16进制数扩展成8位16进制数。所以前面变成了0000
4 int 则表明了 0x0000 0200这个地址存放的整型数据。
清楚了上面的结构来进一步研究,则*(…) 其实就相当于取0x00000200处的内容.再将这个内容作为地址,放的是一个char型数据,也就是说buffer代表的是一个地址常量。
通过上面的汇编代码清晰的验证了这一点。
在此再次总结两个要点:1,括号里面的*用来赋予数据实际意义,来告诉我们后面的数据是一个地址,而不是一个数据。2括号外面的*用来告诉我们我们要取地址里面的内容,深入理解以上两点对于C语言指针的理解十分必要!
其实又重新引入了这样一个问题:我们为什么大费周折的让buffer等于一个地址里面的内容,而不是直接等于这个地址?这样做的意义何在
顺带思考buffer[0] = 0,&buffer,buffer = 0
如果是承接上面的内容,那么无疑地,&buffer虽然本意是要取buffer的地址,但这样的操作是错误的,因为#define定义的是常量,而常量可以认为是标号,没有被分配给地址空间,编译的时候直接赋予相应的值,只有变量才有取地址的意义,同样的对buffer进行赋值同样不正确。而buffer[0] = 0这个操作是合理的,因为这是一个有意义的操作,是将ds:buffer+0处的内存赋值为0,是有确定的含义的。
进一步,我们发现删除掉buffer = (char*)malloc(20);
发现程序编译连接仍让能够通过,说明了上述语句并不是赋值语句?