C 定义功能宏:编译器参数与源代码?

C 定义功能宏:编译器参数与源代码?,c,macros,C,Macros,我最近遇到了一个功能宏\u POSIX\u C\u SOURCE,它允许在包含包含POSIX函数(例如(,也即将发布到C23)或()的头时指定所需的最低POSIX版本。启用strdup的正确方法是定义\u POSIX\u C\u SOURCE至少200401L(2004年,版本1),对于clock\u gettime至少200101L。一些库供应商可能不会编写检查/#ifs来启用或禁用函数声明,这会使一些程序在程序员未定义功能宏时无法使用其他库实现进行编译 有两种方法可以启用POSIX功能 1

我最近遇到了一个功能宏
\u POSIX\u C\u SOURCE
,它允许在包含包含POSIX函数(例如(
,也即将发布到C23)或(
)的头时指定所需的最低POSIX版本。启用
strdup
的正确方法是定义
\u POSIX\u C\u SOURCE
至少
200401L
(2004年,版本1),对于
clock\u gettime
至少
200101L
。一些库供应商可能不会编写检查/
#ifs
来启用或禁用函数声明,这会使一些程序在程序员未定义功能宏时无法使用其他库实现进行编译


有两种方法可以启用POSIX功能

1.包含前定义 在源文件中

#if !defined _POSIX_C_SOURCE || _POSIX_C_SOURCE < 200401L
#  error the minimum required POSIX version is 2004.1
#endif
#include <time.h>
#include <string.h>
#如果!定义的POSIX_C_SOURCE | | POSIX_C_SOURCE<200401L
#错误:要求的最低POSIX版本为2004.1
#恩迪夫
#包括
#包括
我考虑插入检查,因为源文件可能以不同的方式编译(其他编译器、其他buildchain、其他makefile等),这可以防止丢失编译器参数


我认为第一个最快,但第二个更干净

问题
  • 如果在定义要素宏之前包含标题,则第一个标题是否有问题?(见下面的代码)
  • 由于文件现在包含版本号(大于默认值),是否启用了以前禁用的功能
  • 有没有更好的方法来定义和确保这些宏
  • #包括
    #包括
    ...
    #定义\u POSIX\u C\u源200401L
    #包括
    #包括
    
    这些定义肯定属于源代码,因为它们说明了代码的要求。如果您的代码需要一个feature宏,您基本上是说它需要(某些)宏将启用的函数。如果您没有将其放入源文件,您将如何记录它

    不要尝试做一些花哨的事情,比如在你的例子中,你包含了一些标题。这显然不适用于几乎所有情况


    不建议从编译器命令行定义功能宏。这些信息应该只用于将编译时信息传递给在编写代码时不知道的代码。例如,版本号或用于启用/禁用代码的可选行为。

    头文件通常使用guard宏,以便头文件的大部分在每个编译单元中只进行一次有条件编译。因此,需要在第一次包含头文件之前定义feature宏。我认为直接在源代码中的第一种方式更合适。我不确定这是否是一种更好的方式,但一种选择是在头文件中定义功能测试宏,并将其包含在.c文件中。同样,您可以在源代码本身(即ridiculos)中定义/更改语言标准。添加
    -D_POSIX_C_SOURCE=…
    将具有与
    -std=…
    选项类似的含义,只是更改库的标准版本而不是语言。在编写仅标题库时,需要POSIX标准的最低版本以及所述的
    #if-#error
    构造是唯一的选择。您不希望将
    \u POSIX\u C\u SOURCE
    的值更改为在头中更改。
    gcc ... -D_POSIX_C_SOURCE=200401L
    
    #if !defined _POSIX_C_SOURCE || _POSIX_C_SOURCE < 200401L
    #  error the minimum required POSIX version is 2004.1
    #endif
    #include <time.h>
    #include <string.h>
    
    #include <time.h>
    #include <string.h>
    ...
    #define _POSIX_C_SOURCE 200401L
    #include <time.h>
    #include <string.h>