zoukankan      html  css  js  c++  java
  • C语言中函数名称和宏名称同名

      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。




  • 相关阅读:
    A query was run and no Result Maps were found for the Mapped Statement 'com.demo.dao.UserDao.check'. It's likely that neither a Result Type nor a Result Map was specified.
    layui监听input内容变动简单粗暴
    Java多线程中
    Java 对象内存分析
    MySQL重做日志
    并查集-Java实现
    java虚拟机类加载机制
    Java的23种设计模式概述
    redo log 有什么作用?
    什么是redo log ?
  • 原文地址:https://www.cnblogs.com/menggucaoyuan/p/2832822.html
Copyright © 2011-2022 走看看