代码改变世界

C语言中函数名称和宏名称同名

2012-12-25 17:45  menggucaoyuan  阅读(1463)  评论(1编辑  收藏

  C语言中,函数名称和宏名称可以相同。可以参考下面的示例程序。
///////////////////////////////////////////test.cpp
#include <stdio.h>


void print(int value) {
printf("%d\n", value);
}


#define print(x) printf("hello"); \
print(x)


int main() {
print(23);


return 0;
}
  上面的程序在vc和gcc下都可以运行,输出结果是:hello23。
  究其原因,我们知道编译器编译C语言程序时,先执行预编译,然后再执行编译、汇编和链接等步骤。预编译阶段质主要处理宏,而编译阶段同名的宏已经被替换掉了,故而此时是不存在标识符冲突的。
但是,函数名称和宏名称同名是有前提的,同名的宏定义必须在同名函数实体之下。再请参考下面示例程序。
/////////////////////////test.cpp
#include <stdio.h>

#define print(x) printf("hello"); \
print(x)


void print(int value) {
printf("%d\n", value);
}


int main() {
print(23);


return 0;
}
  这个程序是编译不过去的,因为宏定义在同名函数定义之前,预编译到print函数时,其名称也被当做宏进行处理,预编译完毕后,编译器编译是程序显然是不对的。如果程序的文件名称是test.c,则linux环境可以通过命令gcc -E test.c > test.i,可以看到预编译结果,有心者可以自己分析下,仔细看看print函数的预编译结果。
如果要定义一个与函数名同名的函数,我们须在函数定义之后再定义宏,似乎不太优雅,没有别的方法么?有的,多文件实现之。有多文件及其源码如下:
/////////////////////////print.h
#ifndef __PRINT_H__
#define __PRINT_H__


void print(int value);


#endif


/////////////////////////print.cpp
#include "print.h"
#include <stdio.h>


void print(int value) {
printf("%d\n", value);
}


/////////////////////////print_inf.h
#ifndef __PRINT_INF_H__
#define __PRINT_INF_H__


#include "print.h"


//print macro
#define print(x) printf("hello"); \
print(x) //print function


#endif

 


/////////////////////////test.cpp
#include "print_inf.h"
#include <stdio.h>

int main() {
print(23);


return 0;
}
  编译程序命令是gcc test.c print.c -o test,运行程序test,输出是hello23。
  okay,问题又一次解决。此时,可能有一个疑问,宏与函数同名,有什么用?还是仅仅为了炫耀?
  考虑如下场景,如果程序库print版本更新,我觉得print.h中的print函数功能有限,需要扩充一下,实现一个print_ex函数,而此时我没有定义一个print宏,调用这个print函数的地方改怎么办?
  当然可以把调用旧版本print函数的代码都更新为print_ex函数,当然,你得费力费心。
  但是,如果旧版本库做的比较好,而且考虑周全,已经定义了一个与print函数同名的print宏呢?我是不是仅仅把print宏中的print函数更改为print_ex就可以了?是不是很方便?而且,不管新版本的函数名称如何更改,因为一个宏的存在,调用print库用户不必关心新版本更新了那些内容,也无需更改代码,仅仅重新编译程序即可。新的示例代码如下:
/////////////////////////print.h
#ifndef __PRINT_H__
#define __PRINT_H__


void print(int value);
void print_ex(int value);


#endif


/////////////////////////print.cpp
#include "print.h"
#include <stdio.h>


void print(int value) {
printf("%d\n", value);
}


void print_ex(int value) {
printf("%d\n", value + 10);
}


/////////////////////////print_inf.h
#ifndef __PRINT_INF_H__
#define __PRINT_INF_H__


#include "print.h"


//print macro
#define print(x) printf("hello"); \
print_ex(x) //print function


#endif


/////////////////////////test.cpp
#include <stdio.h>
#include "print_inf.h"


int main() {
print(23);


return 0;
}
  上面编译程序命令同样是gcc test.c print.c -o test,运行程序test,输出是hello33。