C“ stdio.h”函数别名/重命名

问题描述

我正在尝试重命名“ stdio.h”函数或至少为其命名一个别名。我尝试过:

#include <stdio.h>
#define printf() test()

int main() {
    teste("Hello World!\n");
    return 0;
}

但没有成功,我也尝试下载stdio.h源代码并对其进行编辑,但是它收到了太多警告,并且未按预期运行。

解决方法

您需要先放置宏名称,然后删除括号:

#define test printf

或者,如果您需要括号和参数:

#define test(...) printf(__VA_ARGS__);

请注意,此类宏仅对测试代码功能“模拟”有意义。仅出于此目的而重命名,或者为了创建自己的“秘密宏语言”而重命名是非常糟糕的做法。

,

这个想法是基于printf()定义一个宏。这是定义自制调试/日志服务的常用方法。

有一些陷阱需要避免:

  1. 请勿放置“;”在宏的末尾,否则您可能会面临 在“ if / else”语句中使用宏并将您放置在 终止的“;”在宏之后:
#define test(...) printf(__VA_ARGS__);

int main(void)
{
  if (1)
    test("message 1\n");
  else
    test("message 2\n");
    
  return 0;
}

编译器将显示如下错误:'else' without a previous 'if'

因此,最好在定义宏时不以“;”结尾:

#define test(...) printf(__VA_ARGS__)
  1. 强制使用格式字符串,否则将出现以下错误:
#define test(...) printf(__VA_ARGS__)

int main(void)
{
  char *str = "foo%bar";
    
  test(str);

  return 0;
}

编译器将发出警告:format not a string literal and no format arguments [-Wformat-security],因为字符串中有一个“%”。

因此,最好将宏定义为:

#define test(format,...) printf(format,__VA_ARGS__)

int main(void)
{
  char *str = "foo%bar";

  test("%s",str);

  return 0;
}
  1. 但是如果您要打印不带任何格式说明符的字符串,例如:
#define test(format,__VA_ARGS__)

int main(void)
{
  test("A string without format specifiers\n");

  return 0;
}

由于变量部分(即__VA_ARGS__)为空,因此编译器将引发错误:

error: expected expression before ')' token
6 | #define test(format,__VA_ARGS__)

为防止这种情况,可以使用预处理器“ ##”技巧(它是GCC特定的扩展名):

#define test(format,##__VA_ARGS__)

int main(void)
{
  test("A string without format specifiers\n");

  return 0;
}
  1. 当然,由于宏使用对服务函数(printf()的调用,因此请包含定义宏的相应头文件(<stdio.h>):
#include <stdio.h>

#define test(format,##__VA_ARGS__)

int main(void)
{
  test("A string without format specifiers\n");

  return 0;
}

最后,为避免在使用C语言编写宏时避免所有前面的陷阱以及许多其他陷阱,我可以建议Best practices for the C language preprocessor