C 宏隐藏函数及其地址

C 宏隐藏函数及其地址,c,macros,variadic-macros,C,Macros,Variadic Macros,我正在用C编写一个库。我有一个函数,应该可以供库的用户使用。当某个值被定义为1时,应该编译并执行它,但当该值被定义为0时,根本不应该编译它。用法应该被void0替换,void0将被优化掉 我想,我可以使用宏来实现这一点,比如: #include <stdio.h> #include <stdarg.h> #define ENABLE_PRINT_NUMBERS 0 #if ENABLE_PRINT_NUMBERS void print_numbers(int numb

我正在用C编写一个库。我有一个函数,应该可以供库的用户使用。当某个值被定义为1时,应该编译并执行它,但当该值被定义为0时,根本不应该编译它。用法应该被void0替换,void0将被优化掉

我想,我可以使用宏来实现这一点,比如:

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

#define ENABLE_PRINT_NUMBERS 0

#if ENABLE_PRINT_NUMBERS
void print_numbers(int number, ...);
#endif

#if !ENABLE_PRINT_NUMBERS
#define print_numbers(number, ...) (void)0
#endif

#if ENABLE_PRINT_NUMBERS
void print_numbers(int number, ...) {
    va_list va;
    va_start(va, number);
    const int second_number = va_arg(va, int);
    va_end(va);

    printf("numbers: %d, %d\n", number, second_number);
}
#endif

int main() {
    printf("## Shadowing by macro - test ##\n\n");

    print_numbers(1, 2);

    printf("function address: 0x%x\n", (void*)&print_numbers);

    return 0;
}
但是,如果未编译此类函数,则定义ENABLE_PRINT_NUMBERS 1,&PRINT_NUMBERS不会被声明。有没有一种方法可以编写宏,这样就可以声明用法和函数的地址?只使用函数名编写第二个define会导致之前在此处定义的print_编号出错

我希望避免使用特殊的空函数,因为这个库中有15个其他函数需要在发行版中删除。这个库是为嵌入式设备设计的,我希望内存占用尽可能小

要明确的是:
我不想得到像宏这样的函数的地址。我希望这个函数的地址有一些值,最好是空的,因为这个函数的地址在库中的许多地方使用,我正在尝试尽可能少地修改库。使用这种地址的地方会检查指针是否为空,因此不会导致未定义的行为。

宏在编译之前被处理,称为预处理。因此,当条件为false时,if块中的代码部分在编译开始时不存在

传递给实际C编译器的结果C文件为:

int main() {
    printf("## Shadowing by macro - test ##\n\n");

    (void)0;

    printf("function address: 0x%x\n", (void*)&print_numbers);

    return 0;
}
宏是文本形式的,这是一种简化,但对于在预处理过程中替换的这个问题的范围来说已经足够了


没有函数定义,因此没有它的地址。

宏在编译之前被处理,称为预处理。因此,当条件为false时,if块中的代码部分在编译开始时不存在

传递给实际C编译器的结果C文件为:

int main() {
    printf("## Shadowing by macro - test ##\n\n");

    (void)0;

    printf("function address: 0x%x\n", (void*)&print_numbers);

    return 0;
}
宏是文本形式的,这是一种简化,但对于在预处理过程中替换的这个问题的范围来说已经足够了


没有函数定义,因此没有它的地址。

您用错误的方法处理这个问题

应用程序代码应该检查ENABLE_PRINT_number,以查看是否调用有问题的函数

int main() {
    printf("## Shadowing by macro - test ##\n\n");

#ifdef ENABLE_PRINT_NUMBERS
    print_numbers(1, 2);

    printf("function address: 0x%x\n", (void*)&print_numbers);
#else
    printf("print_numbers not defined, do something else instead\n");
#endif

    return 0;
}

这是应用程序代码检查库的不同版本中是否存在特定功能的普遍接受的方法。

您的做法是错误的

应用程序代码应该检查ENABLE_PRINT_number,以查看是否调用有问题的函数

int main() {
    printf("## Shadowing by macro - test ##\n\n");

#ifdef ENABLE_PRINT_NUMBERS
    print_numbers(1, 2);

    printf("function address: 0x%x\n", (void*)&print_numbers);
#else
    printf("print_numbers not defined, do something else instead\n");
#endif

    return 0;
}

这是应用程序代码检查库的不同版本中是否存在特定功能的普遍接受的方法。

您需要的是函数指针,而不是类似函数的宏,如果打印号不可用/启用打印号为0,则可以将其初始化为空指针:

旁注:

类似宏的函数在内存中没有地址。宏在编译之前由预处理器展开。任何试图获取甚至打印其地址的行为都违反了C语法

printffunction地址:0x%x\n,void*&打印\u编号;打印函数地址是错误的。x转换说明符需要类型为unsigned int的参数,而C标准不允许将函数指针强制转换为空指针

事实上,我发现打印函数地址几乎是不可能的,我发现,使用从指向函数的指针到无符号字符指针的转换以及一些打印技巧,而不是一种方法。我用了那种方法


您需要的是一个函数指针,而不是一个类似于宏的函数,如果打印编号不可用/启用打印编号为0,则可以将其初始化为空指针:

旁注:

类似宏的函数在内存中没有地址。宏在编译之前由预处理器展开。任何试图获取甚至打印其地址的行为都违反了C语法

printffunction地址:0x%x\n,void*&打印\u编号;打印函数地址是错误的。x转换说明符需要类型为unsigned int的参数,而C标准不允许将函数指针强制转换为空指针

事实上,我发现打印函数地址几乎是不可能的,我发现,使用从指向函数的指针到无符号字符指针的转换以及一些打印技巧,而不是一种方法。我用了那种方法


是的,我同意,但是如何处理这个函数指针呢?我希望它是空的,但是如何用宏实现它似乎并不明显。名为print_numbers的对象不存在。那么你想如何得到它的地址呢?你看到了吗
预处理后,print_numbers函数的定义在代码中的某个地方。我在问题中添加了一个澄清。谢谢你的回答:是的,我同意,但是如何处理这个函数指针呢?我希望它是空的,但是如何用宏实现它似乎并不明显。名为print_numbers的对象不存在。那么你想如何得到它的地址呢?在预处理后的代码中,您是否看到print_numbers函数的定义。我在问题中添加了一个说明。谢谢你的回答:我不明白为什么你会尝试获取和打印一个函数的地址,比如宏,而不是定义的函数?宏就是编译前展开的宏。它在内存中没有地址。任何这样做的尝试都是违反C语法的,编译器应该提供一个错误。我不想得到类似于宏的函数的地址。我希望此函数的地址有一些值,最好是null,因为此函数的地址在库中的许多位置都使用,我正在尝试尽可能少地修改。我不明白为什么您会尝试获取和打印类似宏的函数的地址,而不是已定义的函数的地址?宏就是编译前展开的宏。它在内存中没有地址。任何这样做的尝试都是违反C语法的,编译器应该提供一个错误。我不想得到类似于宏的函数的地址。我希望这个函数的地址有一些值,最好是null,因为这个函数的地址在库中的很多地方都有使用,我正在尝试尽可能少地修改它。