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

C 用预处理器指令替换函数头,c,debugging,directive,C,Debugging,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"); retur

出于调试原因,我创建了以下代码示例:有一个函数
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;
}

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

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

翻译单元是正在编译的源文件,包括它包含的所有文件。要使用预处理器宏,必须在翻译单元中定义它。通常的做法是,在名为
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
时,宏替换将更改定义,编译器会抱怨的。一种方法是在包含头文件后,将
#undefa
放入定义
a
的源文件中

另外,由于
a_debug
非常简单,因此可以在头文件中将其定义为静态内联函数。不要将上面显示的定义放在源文件中,并将其声明放在头文件中,而是将其放在头文件中:

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);
}

您是将宏放在声明
a()
的头文件中,还是放在提供
a
实现的C文件中?如果宏在标题中不可见,则调用函数将不知道它并直接转到
a
,而不通过
a_debug
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);
}