用预处理器指令替换函数头

Displace function header with preprocessor directive

出于调试原因,我创建了以下代码示例:有一个函数 a(),它由函数 b() 调用。我想知道调用 a() 的函数的名称。所以我创建了下面的代码,它工作正常:

#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <stdarg.h>

uint8_t a(uint8_t k)
{
    printf("function: a\n");
    return k;   
}

uint8_t a_debug( uint8_t j, char const *caller_name)
{
    uint8_t rtv; 
    printf("a was called by %s\n", caller_name);
    rtv = a(j);
    return rtv;
}

#define a(x) a_debug(x,__func__)

void b()
{
    uint8_t asdf;
    asdf = a(5);
    printf("asdf = %u", asdf);
}

int main(int argc, char **argv)
{
    b();
    
    return 0;
}

在一个更大的软件项目中,我粘贴了代码


uint8_t a_debug( uint8_t j, char const *caller_name)
{
    uint8_t rtv; 
    printf("a was called by %s\n", caller_name);
    rtv = a(j);
    return rtv;
}

#define a(x) a_debug(x,__func__)

在函数 a() 的正下方调试函数 a()。我可以构建和执行软件项目,但从未输入函数 a_debug()。而不是直接执行函数a()。我必须在哪个文件或确切位置定义预处理器指令 #define a(x) a_debug(x,__func__) 以便编译器将 a() 替换为 a_debug() 函数?

预处理器指令在它们出现的翻译单元中运行。

翻译单元是正在编译的源文件,包括它包含的所有文件。要使用预处理器宏,它必须在翻译单元中定义。通常这样做的方式是在名为 foo.c 的文件中定义一个包含一些名为 foo 或与某些类别或想法 foo 相关的函数的源文件,并且这些函数的声明是放入名为 foo.h 的文件。头文件 foo.h 应提供使用 foo.c.

提供的工具所需的任何预处理器宏、声明和其他内容

首先,您可以将新函数 a_debug 放入包含 a 的源文件中。另外,你可以简化它;不需要变量 rtv:

uint8_t a_debug(uint8_t j, char const *caller_name)
{
    printf("a was called by %s.\n", caller_name);
    return a(j);
}

然后,在声明a的头文件中,需要添加两个东西。首先,声明 a_debug:

uint8_t a_debug(uint8_t, char const *);

二、宏的定义a:

#define a(x) (a_debug((x), __func__))

但是,这会导致一个问题。定义 a 的源文件应该包含它自己的头文件。 (这样做的一个原因是允许编译器检查函数声明与函数定义不匹配等错误。)但是当它包含头文件时,将定义 a 宏,然后,当函数 a 被定义,定义将被宏替换改变,编译器将报错。解决此问题的一种方法是将 #undef a 放入定义 a 的源文件中,在它包含其头文件之后。

还有,既然a_debug这么简单,你可以在header中定义为静态内联函数。不要将上面显示的定义放在源文件中,而将其声明放在头文件中,而是将其放在头文件中:

static inline uint8_t a_debug(uint8_t j, char const *caller_name)
{
    printf("a was called by %s.\n", caller_name);
    return a(j);
}