【问题标题】:Replacing function call (and not declaration) with define C用define C替换函数调用(而不是声明)
【发布时间】:2019-01-23 05:48:01
【问题描述】:

我尝试使用define替换函数调用,但我找不到如何只替换调用而不替换声明。

IE:

#define test(); printf("worked\n");

void test()
{
printf("how sad ?\n");
}

int main()
{
test();
}

我无法在函数之后创建我的定义(项目规则)

问题是:我希望定义中“test()”之后的分号只替换调用,但它也替换了声明。

我尝试用谷歌搜索并没有任何结果,这真的可能吗?奇怪的是它没有采用文字表达。

【问题讨论】:

    标签: c c-preprocessor


    【解决方案1】:

    需要注意的几点:

    • #define 不需要 大括号 () - 仅在需要处理参数时使用它们
    • 语法不包含分号:#define test printf
    • 像这样(有点模糊)调用像printf() 这样的函数可能会有风险,尤其是在调用者不希望他们的字符串用作格式字符串的情况下。首选#define test(msg) printf("%s", msg)
    • #define test ... 之后,预处理器将愚蠢地 替换test所有 实例 - 因此函数声明实际上将读取void printf("worked\n"); { ... }

    结果应该是:

    #include <stdio.h>
    
    #define test(msg) printf("%s\n", msg)
    
    void main(void) {
        test("hello");
    }
    

    或:

    #include <stdio.h>
    
    void test(const char *msg) {
        printf("%s\n", msg);
    }
    
    void main(void) {
        test("hello");
    }
    

    如果您尝试使用#define 来重定向函数调用,那么您必须使用不同的符号...例如:

    #include <stdio.h>
    
    /* Comment / uncomment this to change behaviour */
    #define REDIRECT_TEST
    
    #ifdef REDIRECT_TEST
    #  define my_test(msg) printf("REDIRECTED:%s\n", msg)
    #else
    #  define my_test      test    
    #endif
    
    void test(const char *msg) {
        printf("%s\n", msg);
    }
    
    void main(void) {
        my_test("hello");
    }
    

    【讨论】:

    • 感谢您的回答。可悲的是,我的项目真的限制了我,我不能使用你的解决方案。我将不得不手动完成。
    • #define test(); printf("worked\n"); 实际上意味着当你写test() 时它会输出; printf("worked\n"); (注意额外的分号)......(或者我错了吗?)
    【解决方案2】:

    您应该在单独的头文件中进行定义。并且定义不应包含分号。 所以你的代码应该是这样的:

    replace_test.h:

    #define test() dummy_test()
    

    test.h:

    void test();
    

    test.c:

    void test()
    { your test code}
    

    dummy.c:

    void dummy_test()
    {
     your dummy code here (printf("worked!"); etc.
    }
    

    program.c:

    //decide which behavior you want, either include replace_test.h or test.h header
    #include "replace_test.h"
    //#include "test.h"
    
    int main()
    {
       test();
    }
    

    【讨论】:

    • 你能解释一下为什么你认为答案是完全错误的???据我所知,这是在 c 中使用带有宏的模拟的常用方法。在标题处定义,并根据需要使用虚拟标题。
    • 您使用名称 test 执行宏,然后使用相同名称 test 运行。什么?
    • 宏和函数可以同名。仅当文件 test.c 或 test.h 包含到 replace_test.h 时才会导致问题。在使用代码(program.c)中,用户可以决定是否包含真正的test.h头文件,并真正调用函数test(),或者包含replace_test.h头文件,并拥有调用'test的代码()' 替换为对 'dummy_test()' 方法的调用。
    • 顺便说一句,关于我之前提到的模拟方法,正如我所提到的,有一种使用宏的方法,另一种方法是使用函数指针,根据需要将指针指向虚拟实现。
    • 那就好好解释吧。
    【解决方案3】:

    printf 有一个“可变参数”。如果您不使用该 q/a 中的任何解决方案,有时您会遇到问题:"How to wrap printf() into a function or macro?"

    这样的一些提示,例如:

    #define MY_PRINTF(...) printf(__VA_ARGS__)
    

    或者这个:

    #define MY_PRINTF(f_, ...) printf((f_), ##__VA_ARGS__)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-04-01
      • 1970-01-01
      • 2018-03-14
      相关资源
      最近更新 更多