如何创建用于将 /n 附加到每个 printf 的 C 宏
How to create a C macro for appending /n to every printf
MY_PRINT
是贯穿整个代码的一个宏,它只是做printf。
我想暂时修改它以在每个 printf 之后也附加 \n。
但是,当我这样做时:
#define SENS_PRINT(x) printf(x); printf("\n")
MY_PRINT( "\n #%d: %c ", ++command_line_number, sensor_operation_code );
...输出是垃圾:#3405240: <alpha symbol>
打印正常,但末尾没有 \n:
#define SENS_PRINT printf
函数行宏的问题在于预处理将所有以逗号分隔的参数视为宏的参数,而不是单个参数。所以你的编译器真的应该抱怨你向宏传递了很多参数。
一个简单的解决方案是将宏参数括在括号中:
MY_PRINT( ( "\n #%d: %c ", ++command_line_number, sensor_operation_code ) );
// ^ ^
// | |
// Note extra parentheses here... and here
另一个解决方案是使用variadic macros。
在某种程度上相关的注释中,如您所示,您的宏不能用于构造,例如
if (some_condition)
MY_PRINT(...);
那将被替换为
if (some_condition)
printf(...);
printf(...);
如果宏中有多个语句,则需要将其包含在一个块中,例如
#define MY_PRINTF(...) \
do { \
statement1; \
statement2; \
. \
. \
. \
statementN; \
} while (0)
您希望您的宏能够接受各种参数,就像真正的 printf 一样。您可以使用可变参数宏来做到这一点。
当宏是条件代码块中的唯一表达式时,两个单独的表达式不会被解释为宏建议的也存在危险。想想如果你说 if (flag) SENS_PRINT(...);
宏会做什么。防止这种情况的一种方法是将宏包装在 do { ... } while(0)
块中。
将换行符附加到 printf
的可变参数宏可能如下所示:
#define PRINTFLN(...) do { printf(__VA_ARGS__); puts(""); } while (0)
你可以像printf
一样使用它:
PRINTFLN("Hello %s!", "cruel world");
if (flag) PRINTFLN("%d + %d == %d", x, y, sum);
C 语言允许您连接由空格分隔的字符串文字。如果您对 MY_PRINT
的所有调用都使用字符串文字作为它们的格式参数,您可以定义一个可变参数宏,它将直接将 "\n"
附加到您的格式字符串,然后应用其余参数。
像这样定义你的宏
#define MY_PRINT(format, ...) printf(format "\n", __VA_ARGS__)
您将能够直接将换行符附加到格式化参数。
使用此方法只会执行一个函数调用,但任何使用字符串文字以外的任何格式的调用都会导致编译错误。
MY_PRINT
是贯穿整个代码的一个宏,它只是做printf。
我想暂时修改它以在每个 printf 之后也附加 \n。
但是,当我这样做时:
#define SENS_PRINT(x) printf(x); printf("\n")
MY_PRINT( "\n #%d: %c ", ++command_line_number, sensor_operation_code );
...输出是垃圾:#3405240: <alpha symbol>
打印正常,但末尾没有 \n:
#define SENS_PRINT printf
函数行宏的问题在于预处理将所有以逗号分隔的参数视为宏的参数,而不是单个参数。所以你的编译器真的应该抱怨你向宏传递了很多参数。
一个简单的解决方案是将宏参数括在括号中:
MY_PRINT( ( "\n #%d: %c ", ++command_line_number, sensor_operation_code ) );
// ^ ^
// | |
// Note extra parentheses here... and here
另一个解决方案是使用variadic macros。
在某种程度上相关的注释中,如您所示,您的宏不能用于构造,例如
if (some_condition)
MY_PRINT(...);
那将被替换为
if (some_condition)
printf(...);
printf(...);
如果宏中有多个语句,则需要将其包含在一个块中,例如
#define MY_PRINTF(...) \
do { \
statement1; \
statement2; \
. \
. \
. \
statementN; \
} while (0)
您希望您的宏能够接受各种参数,就像真正的 printf 一样。您可以使用可变参数宏来做到这一点。
当宏是条件代码块中的唯一表达式时,两个单独的表达式不会被解释为宏建议的也存在危险。想想如果你说 if (flag) SENS_PRINT(...);
宏会做什么。防止这种情况的一种方法是将宏包装在 do { ... } while(0)
块中。
将换行符附加到 printf
的可变参数宏可能如下所示:
#define PRINTFLN(...) do { printf(__VA_ARGS__); puts(""); } while (0)
你可以像printf
一样使用它:
PRINTFLN("Hello %s!", "cruel world");
if (flag) PRINTFLN("%d + %d == %d", x, y, sum);
C 语言允许您连接由空格分隔的字符串文字。如果您对 MY_PRINT
的所有调用都使用字符串文字作为它们的格式参数,您可以定义一个可变参数宏,它将直接将 "\n"
附加到您的格式字符串,然后应用其余参数。
像这样定义你的宏
#define MY_PRINT(format, ...) printf(format "\n", __VA_ARGS__)
您将能够直接将换行符附加到格式化参数。
使用此方法只会执行一个函数调用,但任何使用字符串文字以外的任何格式的调用都会导致编译错误。