一个宏定义引发的问题

问题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);

发现程序编译连接仍让能够通过,说明了上述语句并不是赋值语句?

时间: 2024-10-04 01:34:04

一个宏定义引发的问题的相关文章

【c语言】写一个宏定义,实现的功能是将一个int型的数的奇偶位互换

// 写一个宏定义,实现的功能是将一个int型的数的奇偶位互换,例如6的二进制为0110,第一位与第二位互换, // 第三位与第四位互换,得到1001,输出应该为9 #include <stdio.h> // 取出奇数位与偶数位,奇数位左移1位,偶数位一位,相加或者相或 #define EXCHANGE(num) (((0x55555555 & num) << 1) + ((0xaaaaaaaa & num) >> 1)) int main() { pr

宏定义引发的困惑

最近使用一个开源库,代码中使用的名称为min和max的两个函数与WinDef.h里定义的相同名称的宏定义冲突, 提示各种离奇错误.最后使用了NOMINMAX的预处理器定义解决此问题.说明:宏定义虽方便,不能滥用. #ifndef NOMINMAX #ifndef max #define max(a,b)            (((a) > (b)) ? (a) : (b)) #endif #ifndef min #define min(a,b)            (((a) < (b))

快速排序变种实现:一次宏定义引发的熬夜事件

一.背景 睡前忽然想写两行代码练练手,想起快速排序的一种变种实现,于是写了快速排序,在理论上完全没问题的情况下测试结果却很诡异,debug半天发现是宏定义导致,作为经验教训记录下来. 二.快速排序变种实现 原理: |_| |_| |_________________________________________| L    R                     unSorted -------------------------------------------------------

请写出一个宏定义,用以判断一个C是否是字母字符,若是,得1,否则得0

#include<stdio.h> #define M (a>='a'&&a<='z')?1:0 #define N (a>='A'&&a<='Z')?1:0 #include<stdlib.h> main() { char a; int b; scanf("%c",&a); if(a>='a') b=M; else b=N; printf("%d\n",b); syste

当结构体遇上宏定义,以及函数指针的高级写法(结构体中能用宏定义一个函数?)

一.结构体中可以定义一般的宏定义 如: struct aaa{   #define STATUS_1 100   #define STATUS_2 200   #define STATUS_3 300   ........}: 首先,这里的宏定义是在预编译阶段完成的,编译器此时并不知道什么结构体,所以这些宏是全局可见的.   一个宏定义,如果写在结构体之内,即使与结构体之外的宏定义名字重复了最多是编译警告.可是如果不在结构体之内,名字重复可肯定是error.(未证实,可以做实验,而且可以把两处的

C中的预编译宏定义

文章来自 http://www.uml.org.cn/c++/200902104.asp 在将一个C源程序转换为可执行程序的过程中, 编译预处理是最初的步骤. 这一步骤是由预处理器(preprocessor)来完成的. 在源流程序被编译器处理之前, 预处理器首先对源程序中的"宏(macro)"进行处理. C初学者可能对预处理器没什么概念, 这是情有可原的: 一般的C编译器都将预处理, 汇编, 编译, 连接过程集成到一起了. 编译预处理往往在后台运行. 在有的C编译器中, 这些过程统统由

C Program基础-宏定义

写好c语言,漂亮的宏定义是非常重要的,我们在阅读别人工程时,往往能看到大量的宏定义,宏定义可以增加代码的可读性,也能增加代码的可移植性,一个好的宏定义甚至是一件艺术品.今天我们就来看看宏定义的方方面面. (一) 宏 vs 函数 在软件开发中过程中,经常有很多重复使用的代码段或功能模块,这些功能既可以用函数实现,也可以用宏实现,那么究竟是用函数好还是宏定义好呢?这就要求我们对二者做合理的取舍. 我们来看下面的例子,求两个数的较大者: (1)宏定义: #define Max(a, b) ((a) >

【转】C语言中DEFINE简介及多行宏定义

要写好C语言,漂亮的宏定义是非常重要的.宏定义可以帮助我们防止出错,提高代码的可移植性和可读性等. 在软件开发过程中,经常有一些常用或者通用的功能或者代码段,这些功能既可以写成函数,也可以封装成为宏定义.那么究竟是用函数好,还是宏定义好?这就要求我们对二者进行合理的取舍. 我们来看一个例子,比较两个数或者表达式大小,首先我们把它写成宏定义: #define MAX( a, b) ( (a) > (b) (a) : (b) ) 其次,把它用函数来实现: int max( int a, int b)

《linux 内核全然剖析》 笔记 CODE_SPACE 宏定义分析

在memory.c里面.遇到一个宏定义,例如以下: #define CODE_SPACE(addr) ((((addr)+4095)&~4095) < current->start_code + current->end_code) 看的第一眼,不知道.第二眼.还是不知道.纠结了半天还是不知道. 睡了一晚,今天早上再看,嘿嘿,竟然看懂了... 这个宏定义用于推断给定的addr线性地址是否位于当前进程的代码段中. 4095 = 0xFFF; addr+4095的作用是将位于0~40