GLib 为常用语言和平台特性提供了一组 C 预处理器宏和符号。

平台

G_OS_WIN32
此宏仅在 Windows 上定义,因此您可以使用 #ifdef G_OS_WIN32 ... #endif 来括号化特定的 Windows 代码。
G_OS_UNIX

此宏仅在 UNIX 和类似操作系统上定义,因此您可以在 #ifdef G_OS_UNIX ... #endif 中括号化特定的 UNIX 代码。要检测是否编译需要特定内核或操作系统的功能,请检查相应的 OS 相关预定义宏,例如

  • Linux 内核(任何 libc,包括 glibc、musl 或 Android):#ifdef __linux__
  • Linux 内核和 GNU 用户空间:
  • FreeBSD 内核(任何 libc,包括 glibc):
  • FreeBSD 内核和用户空间:
  • Apple 操作系统(macOS、iOS、tvOS),无论是否有可用 Cocoa/Carbon 工具包:

更多请见 https://sourceforge.net/p/predef/wiki/OperatingSystems/

G_DIR_SEPARATOR
目录分隔符。在 UNIX 机器上是 '/',在 Windows 下是 '\'
G_DIR_SEPARATOR_S
目录分隔符字符串。在 UNIX 机器上是 "/",在 Windows 下是 "\"
G_IS_DIR_SEPARATOR(ch)
检查一个字符是否为目录分隔符。在 UNIX 机器上对 '/' 返回 true,在 Windows 上对 '\''/' 返回 true。自 2.6 开始可用。
G_SEARCHPATH_SEPARATOR
搜索路径分隔符。在 UNIX 机器上是 ':',在 Windows 下是
G_SEARCHPATH_SEPARATOR_S
搜索路径分隔符字符串。在 UNIX 机器上是 ":",在 Windows 下是 ";"

TRUE
定义了 gboolean 类型的真值。
FALSE
定义了 gboolean 类型的假值。
NULL
定义了标准 NULL 指针。

数学

MIN(a, b)
计算 ab 之间的最小值。
MAX(a, b)
计算 ab 之间的最大值。
ABS(value)

计算给定数值的绝对值。绝对值简单地去掉了任何负号。

例如,

  • ABS(-10) 是 10。
  • ABS(10) 同样是 10。
CLAMP(value, low, high)

确保值在由 lowhigh 设定的限制之间。如果 low 大于 high,则结果未定义。

例如,

  • CLAMP(5, 10, 15) 是 10。
  • CLAMP(15, 5, 10) 是 10。
  • CLAMP(20, 15, 25) 是 20。
G_APPROX_VALUE(a, b, epsilon)

如果给定数值 ab 之间的绝对差小于 epsilon,则返回 true,否则返回 false。

例如,

  • G_APPROX_VALUE (5, 6, 2) 返回 true
  • G_APPROX_VALUE (3.14, 3.15, 0.001) 返回 false
  • G_APPROX_VALUE (n, 0.f, FLT_EPSILON) 如果 n 在单精度浮点 epsilon 从零的范围内,则返回 true

自:2.58

结构访问

结构成员宏 G_STRUCT_MEMBER(member_type, struct_pointer, offset)
返回结构体在指定偏移处的成员,使用给定的类型。
结构指针宏 G_STRUCT_MEMBER_P(struct_pointer, offset)
返回对结构体指定偏移处的无类型指针。
结构偏移宏 G_STRUCT_OFFSET(struct_type, member_name)
返回结构体成员的偏移(以字节为单位)。考虑到在新的代码中使用标准C的 offsetof(),自C89和C++98以来可用,但请注意,offsetof() 返回的是一个 size_t 而不是 long

数组实用程序

数组元素宏 G_N_ELEMENTS(array)
确定数组中的元素数量。数组必须在编译时被声明以便编译器知道它的大小,此宏不能用于堆上分配的数组,只能用于静态数组或堆栈上的数组。

其他宏

这些宏提供了更多的专业特性,这些特性不是那么常被应用程序员使用。

语句开始宏 G_STMT_START
开始多语句宏块,以便在编译器期望只有一个语句的地方使用。
语句结束宏 G_STMT_END
结束多语句宏块,以便在编译器期望只有一个语句的地方使用。
开始声明宏 G_BEGIN_DECLS
用于将可能被C++源代码包含的C头文件括起来(与 G_END_DECLS 一起使用)。如果使用的编译器是C++编译器,则在头文件周围开始一个 extern "C"
结束声明宏 G_END_DECLS
用于将可能被C++源代码包含的C头文件括起来,或者由C++编译器编译的头文件(与 G_BEGIN_DECLS 一起使用)。如果使用的编译器是C++编译器,则在头文件周围结束 extern "C" 块。
参数复制宏 G_VA_COPY(ap1, ap2)

用作复制 va_list 变量的可移植方式。

为了使用此函数,您必须自己包含 string.h,因为此宏可能会使用 memmove(),而GLib不会为您包含 string.h

每次调用 G_VA_COPY (ap1, ap2) 必须与同一函数内部的相应调用 va_end (ap1) 匹配。

这等同于自C99和C++11以来提供的标准C va_copy(),在新代码中应首选使用。

字符串化宏 G_STRINGIFY(macro_or_string)

接受一个宏或一个字符串,并将其转换为预处理器参数扩展后的字符串。例如,以下代码

#define AGE 27
const gchar *greeting = G_STRINGIFY (AGE) " today!";

在预处理器中被转换为(代码等效于)

const gchar *greeting = "27 today!";
拼接宏 G_PASTE(identifier1, identifier2)

从其扩展参数 identifier1identifier2 生成一个新的预处理器拼接标识符 identifier1identifier2。例如,以下代码

#define GET(traveller,method) G_PASTE(traveller_get_, method) (traveller)
const char *name = GET (traveller, name);
const char *quest = GET (traveller, quest);
Color *favourite = GET (traveller, favourite_colour);

在预处理器中被转换为

const char *name = traveller_get_name (traveller);
const char *quest = traveller_get_quest (traveller);
Color *favourite = traveller_get_favourite_colour (traveller);

可用以来:2.20

静态断言宏 G_STATIC_ASSERT(expr)

G_STATIC_ASSERT() 宏让程序员能够在编译时检查条件。条件需要是编译时可计算的。此宏可以在任何 typedef 合法的地方使用。

通常允许在变量声明允许的任何地方声明一个 typedef。因此,您不应该在代码块中使用 G_STATIC_ASSERT()

此宏应在每行源代码中只使用一次。

自从:2.20

静态断言表达式宏 G_STATIC_ASSERT_EXPR(expr)

使用 G_STATIC_ASSERT_EXPR() 宏允许程序员在编译时检查条件。条件必须是编译时可计算的。

G_STATIC_ASSERT()不同,此宏会计算出一个表达式,因此可以在其他表达式的中间使用。其值应该被忽略。这可以通过将其作为逗号表达式的第一个参数来实现。

#define ADD_ONE_TO_INT(x) \
  (G_STATIC_ASSERT_EXPR(sizeof (x) == sizeof (int)), ((x) + 1))

自:2.30

编译器

G_GNUC_EXTENSION
当使用GCC作为编译器时,展开为__extension__。这仅仅告诉GCC在以-pedantic选项编译时不要警告以下非标准代码。
G_GNUC_CONST

当编译器是GCC时,展开为一个GNU C const函数属性。将函数声明为const可以优化对该函数的调用。一个const函数除了检查它的参数外,不再检查任何值,并且除了返回值外没有其他效果。

将属性放在声明之后,分号之前。

gchar g_ascii_tolower (gchar c) G_GNUC_CONST;

更多详情请参阅GNU C文档

具有指针参数并检查所指的数据的函数不得声明为const。同样,通常调用非const函数的函数也不应该是const。对于const函数返回void是没有意义的。

G_GNUC_PURE

当编译器是GCC时,展开为一个GNU C pure函数属性。将函数声明为pure可以优化对该函数的调用。一个pure函数除了它的返回值外没有其他效果,并且返回值仅取决于参数和/或全局变量。

将属性放在声明之后,分号之前。

gboolean g_type_check_value (const GValue *value) G_GNUC_PURE;

更多详情请参阅GNU C文档

G_GNUC_UNUSED

当编译器是gcc时,展开为一个GNU C unused函数属性。它用于声明可能永远不会使用的函数和参数。它避免了可能的编译器警告。

对于函数,将属性放在声明之后,分号之前。它不能放在函数定义中,只能放在声明中。对于参数,将属性放在参数声明开始的位置。

void my_unused_function (G_GNUC_UNUSED gint unused_argument,
                         gint other_argument) G_GNUC_UNUSED;

更多详情请参阅GNU C文档

G_GNUC_MALLOC

当编译器是GCC时,展开为一个GNU C malloc函数属性。

将函数声明为malloc可以优化该函数,但必须完全理解该函数的分配行为,否则可能导致误编译。

一个函数如果返回一个指针,该指针在函数返回时保证不与其他任何有效指针发生别名,并且返回指针所指的任何存储器中都不存在指向有效对象的指针,则可以具有malloc属性。

在实践中,这意味着可以与返回未分配或已清零内存的任何函数一起使用G_GNUC_MALLOC,但不能与返回包含其他指针的初始化结构或进行内存重新分配的函数一起使用。这种定义在GLib 2.58时变更,以与GCC 5引入的更严格定义相匹配。

将属性放在声明之后,分号之前。

gpointer g_malloc (gsize n_bytes) G_GNUC_MALLOC G_GNUC_ALLOC_SIZE(1);

更多详情请参阅GNU C文档

自:2.6

G_GNUC_DEPRECATED

当编译器是GCC时,展开为一个GNU C deprecated属性。它可以用来标记典型为typedef、变量和函数的弃用。当使用-Wdeprecated-declarations选项时,gcc会在使用弃用接口时生成警告。

将属性放在声明之后,分号之前。

int my_mistake (void) G_GNUC_DEPRECATED;

更多详情请参阅GNU C文档

另请参阅:G_DEPRECATED

自:2.2

G_GNUC_DEPRECATED_FOR(func)

类似于 G_GNUC_DEPRECATED,但如果所使用的gcc版本足够新以支持自定义弃用信息,则会指定旧符号的预期替代名称。

将属性放在声明之后,分号之前。

int my_mistake (void) G_GNUC_DEPRECATED_FOR(my_replacement);

更多详情请参阅GNU C文档

注意,如果func是一个宏,它将在警告信息中展开。您可以通过引号括起来以防止这一点。(引号将出现在警告中,但比显示宏展开要好。)

自:2.26

G_GNUC_NORETURN

当编译器为gcc时,扩展为GNU C noreturn函数属性。它用于声明永不返回的函数。它启用函数的优化,并避免可能的编译器警告。

自2.68以来,建议代码使用G_NORETURN而不是G_GNUC_NORETURN,因为它在更多平台和编译器上工作(尤其是MSVC和C++11),而不是仅在gcc和Clang上工作的G_GNUC_NORETURN。由于G_GNUC_NORETURN仍然可以使用,所以还没有弃用。

将属性放在声明之后,分号之前。

void g_abort (void) G_GNUC_NORETURN;

有关更多详细信息,请参阅GNU C文档(英)

G_GNUC_FALLTHROUGH

如果编译器支持,扩展为GNU C fallthrough语句属性。这允许在switch语句中显式声明case语句跳过。

将属性放在您想要跳过的case语句之前。

switch (foo)
  {
  case 1:
    g_message ("it's 1");
    G_GNUC_FALLTHROUGH;
  case 2:
    g_message ("it's either 1 or 2");
    break;
  }

有关更多详细信息,请参阅GNU C文档(英)

自:2.60

G_GNUC_FORMAT(idx)

当编译器为gcc时,扩展为GNU C format_arg函数属性。此函数属性指定函数接受一个格式字符串,用于printf()scanf()strftime()strfmon()风格的函数,并对其进行修改,以便可以将结果传递给格式化函数(格式函数的剩余参数与未修改字符串相同)。

在函数声明之后放置属性,就在分号之前。

gchar *g_dgettext (gchar *domain_name, gchar *msgid) G_GNUC_FORMAT (2);

有关更多详细信息,请参阅GNU C文档(英)

G_GNUC_NULL_TERMINATED

当编译器为gcc时,扩展为GNU C sentinel函数属性。此函数属性仅适用于可变参数函数,并指示编译器检查参数列表是否以显式的NULL终止。

将属性放在声明之后,分号之前。

gchar *g_strconcat (const gchar *string1,
                    ...) G_GNUC_NULL_TERMINATED;

有关更多详细信息,请参阅GNU C文档(英)

自:2.8

G_GNUC_WARN_UNUSED_RESULT

当编译器为gcc时,扩展为GNU C warn_unused_result函数属性。此功能属性使得编译器在忽略函数调用的结果时发出警告。

将属性放在声明之后,分号之前。

GList *g_list_append (GList *list,
                      gpointer data) G_GNUC_WARN_UNUSED_RESULT;

有关更多详细信息,请参阅GNU C文档(英)

自:2.10

G_GNUC_NO_INLINE

当编译器为gcc时,扩展为GNU C noinline函数属性。

将函数声明为noinline可以防止将该函数视为内联函数。

此宏提供作为向后兼容性,最终将被弃用;应使用G_NO_INLINE代替。

可以将该属性放在声明或定义之前,在static关键字之前。

G_GNUC_NO_INLINE
static int
do_not_inline_this (void)
{
// ...
}

有关更多详细信息,请参阅GNU C文档(英)

另请参阅:G_NO_INLINEG_ALWAYS_INLINE

自:2.58

G_GNUC_NO_INSTRUMENT

如果编译器是 GCC,则扩展为 GNU C 的 no_instrument_function 函数属性。具有此属性的函数在编译器指定了 -finstrument-functions 选项时将不被用于分析。

将属性放在声明之后,分号之前。

int do_uninteresting_things (void) G_GNUC_NO_INSTRUMENT;

有关更多详情,请参阅 GNU C 文档

G_GNUC_MAY_ALIAS

如果编译器是 GCC,则扩展为 GNU C 的 may_alias 类型属性。具有此属性的类型将不会受到基于类型的别名分析的约束,但与任何其他类型都假定存在别名,就像 char 一样。

有关详情,请参阅 GNU C 文档

自:2.14

G_GNUC_FUNCTION

在所有现代编译器中扩展为 "",在 GCC 2.x 版本中扩展为 __FUNCTION__。请勿使用它。

已弃用:2.16:使用 G_STRFUNC() 代替

G_GNUC_PRETTY_FUNCTION

在所有现代编译器中扩展为 "",在 GCC 2.x 版本中扩展为 __PRETTY_FUNCTION__。请勿使用它。

已弃用:2.16:使用 G_STRFUNC() 代替

G_GNUC_CHECK_VERSION(major, minor)

扩展为对指定了 __GNUC__ 定义且版本大于或等于提供的次要和主要数字的编译器的检查。例如,以下内容仅适用于类似于 GCC 4.8 或更高版本的编译器。

#if G_GNUC_CHECK_VERSION(4, 8)
// ...
#endif

自:2.42

G_GNUC_BEGIN_IGNORE_DEPRECATIONS

如果编译器是足够新的版本,则通知 GCC(如果已新足够)在调用用 G_GNUC_DEPRECATEDG_GNUC_DEPRECATED_FOR 标记的函数时暂时停止发出警告。这对于一个弃用的函数调用另一个弃用的函数时非常有用,或者当您仍然有弃用函数的回归测试时。

使用 G_GNUC_END_IGNORE_DEPRECATIONS 重新启动警告。 (如果您未使用 -Wdeprecated-declarations 进行编译,则这两个宏都不起作用。)

这个宏可以在函数体内外使用,但必须单独一行。

static void
test_deprecated_function (void)
{
  G_GNUC_BEGIN_IGNORE_DEPRECATIONS
  g_assert_cmpint (my_mistake (), ==, 42);
  G_GNUC_END_IGNORE_DEPRECATIONS
}

这个宏和相应的 G_GNUC_END_IGNORE_DEPRECATIONS 都被认为是语句,因此不应该放在分支或循环条件周围;例如,这种用法是无效的

G_GNUC_BEGIN_IGNORE_DEPRECATIONS
if (check == some_deprecated_function ())
G_GNUC_END_IGNORE_DEPRECATIONS
  {
    do_something ();
  }

并且应将弃用部分移出条件

// Solution A
some_data_t *res;

G_GNUC_BEGIN_IGNORE_DEPRECATIONS
res = some_deprecated_function ();
G_GNUC_END_IGNORE_DEPRECATIONS

if (check == res)
  {
    do_something ();
  }

// Solution B
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
if (check == some_deprecated_function ())
  {
    do_something ();
  }
G_GNUC_END_IGNORE_DEPRECATIONS

自:2.32

G_GNUC_END_IGNORE_DEPRECATIONS

撤销 G_GNUC_BEGIN_IGNORE_DEPRECATIONS 的影响,通知 GCC 重新启动输出警告(假设已经启用了这些警告)。

这个宏可以在函数体内外使用,但必须单独一行。

自:2.32

G_C_STD_VERSION

代码编译时针对的 C 标准版本,它通常使用与兼容 C 标准的编译器相同的 __STDC_VERSION__ 值定义,而在纯 MSVC 中,它使用最低标准版本,因为在这种情况下定义取决于编译标志。

在编译 C++ 编译器时,这将被定义为未定义。

有关更多信息,请参阅 G_C_STD_CHECK_VERSIONG_CXX_STD_VERSION

自:2.76

G_C_STD_CHECK_VERSION(version)

宏用于检查当前编译器是否支持指定的 C 标准版本。此值必须是数字,可以提供已知版本的简写形式(例如 9099…)或完整形式(例如 199000L199901L205503L…)。

当使用 C++ 编译器时,该宏被定义并评估为 false

该值与 G_C_STD_VERSION 进行比较。

#if G_C_STD_CHECK_VERSION(17)
// ...
#endif

有关更多信息,请参阅 G_CXX_STD_CHECK_VERSION

自:2.76

G_CXX_STD_VERSION

代码编译时针对的 C++ 标准版本,它对于兼容 C++ 标准的编译器使用与 __cplusplus 相同的值定义,而在 MSVC 中使用 _MSVC_LANG,因为在这种情况下标准定义取决于编译器中的编译标志。

在不使用 C++ 编译器编译时,这将被定义为未定义。

参见:G_CXX_STD_CHECK_VERSIONG_C_STD_VERSION

自:2.76

G_CXX_STD_CHECK_VERSION(version)

宏用于检查当前编译器是否支持指定的C++标准版本。该值必须为数字,可以提供已知版本的短形式(例如:11、17……)或完整形式(例如:201103L、201703L、205503L……)。

当使用C编译器时,该宏的结果为false。

此值与 G_CXX_STD_VERSION 进行比较。

#if G_CXX_STD_CHECK_VERSION(20)
// ...
#endif

参见:G_C_STD_CHECK_VERSION

自:2.76

G_LIKELY(expr)

提示编译器该表达式很可能评估为真值。编译器可能会使用这些信息进行优化。

if (G_LIKELY (random () != 1))
  g_print ("not one");

自:2.2

G_UNLIKELY(expr)

提示编译器该表达式很可能不评估为真值。编译器可能会使用这些信息进行优化。

if (G_UNLIKELY (random () == 1))
  g_print ("a random one");

自:2.2

G_ALIGNOF(type)

返回平台 ABI 对给定类型值所需的最小对齐方式。给定类型的变量或结构体成员的地址必须是此对齐方式的倍数。例如,大多数平台要求int变量对齐在4字节边界上,所以大多数平台上 G_ALIGNOF (int) 是4。

注意这不一定与 GCC 的 __alignof__ 运算符返回的值相同,它返回类型的推荐对齐方式。首选对齐方式可能比最小对齐方式更严格。

自:2.60

G_SIZEOF_MEMBER(struct_type, member_name)

返回在结构定义中不声明 struct_type 实例的 member_name 的大小(以字节为单位)。

自:2.64

G_NORETURN

根据编译器扩展为 GNU C 或 MSVCnoreturn 函数属性。它用于声明从不返回的函数。启用函数优化,并避免可能的编译器警告。

注意,G_NORETURN 过期了之前的 G_GNUC_NORETURN 宏,它最终将被弃用。 G_NORETURN 支持更多平台。

将属性放置在函数声明之前如下

G_NORETURN void g_abort (void);

自:2.68

G_NORETURN_FUNCPTR

根据编译器扩展为 GNU C 或 MSVCnoreturn 函数属性。它用于声明从不返回的函数指针。启用函数优化,并避免可能的编译器警告。

将属性放置在函数声明之前如下

G_NORETURN_FUNCPTR void (*funcptr) (void);

请注意,如果函数不是函数指针,您可以简单地使用 G_NORETURN 宏如下

G_NORETURN void g_abort (void);

自:2.68

G_ALWAYS_INLINE

根据编译器扩展为 GNU C 的 always_inlineMSVC__forceinline 函数属性。它用于声明始终内联的函数,忽略编译器优化级别。

可以将该属性放在声明或定义之前,在static关键字之前。

G_ALWAYS_INLINE
static int
do_inline_this (void)
{
// ...
}

有关详细信息,请参阅 GNU C 文档和 MSVC 文档

自:2.74

G_NO_INLINE

根据编译器扩展为 GNU C 或 MSVCnoinline 函数属性。它用于声明阻止被考虑内联的函数。

请注意,G_NO_INLINE 过期了之前的 G_GNUC_NO_INLINE 宏,它最终将被弃用。 G_NO_INLINE 支持更多平台。

可以将该属性放在声明或定义之前,在static关键字之前。

G_NO_INLINE
static int
do_not_inline_this (void)
{
// ...
}

自:2.74

G_STRLOC
扩展为表示当前代码位置的字符串。
G_STRFUNC
扩展为表示当前函数的字符串。自2.4起
G_GNUC_INTERNAL

此属性可以用于将库函数标记为仅供库内部使用,这可能会允许编译器更有效地处理函数调用。请注意,静态函数不需要以这种方式标记为内部。有关详细信息,请参阅 GNU C 文档。

当使用支持 GNU C 隐藏可见性属性的编译器时,此宏展开为 __attribute__((visibility("hidden")))。当使用 Sun Studio 编译器时,它展开为 __hidden

请注意,为了提高兼容性,应在函数声明之前放置此属性。虽然 GCC 允许在声明之后使用宏,但 Sun Studio 不允许。

G_GNUC_INTERNAL
void _g_log_fallback_handler (const gchar    *log_domain,
                              GLogLevelFlags  log_level,
                              const gchar    *message,
                              gpointer        unused_data);

自:2.6

G_HAVE_GNUC_VISIBILITY
如果支持 GCC 风格的可见性处理,则定义为 1。

弃用

G_DEPRECATED

这个宏与 G_GNUC_DEPRECATED 相似,可以用于标记函数声明为弃用。与 G_GNUC_DEPRECATED 不同,它是为了跨不同编译器的移植性而设计的,必须放在函数声明之前。

G_DEPRECATED
int my_mistake (void);

自:2.32

G_DEPRECATED_FOR(f)

此宏与 G_GNUC_DEPRECATED_FOR 相似,可以用于标记函数声明为弃用。与 G_GNUC_DEPRECATED_FOR 不同,它是为了跨不同编译器的移植性而设计的,必须放在函数声明之前。

G_DEPRECATED_FOR(my_replacement)
int my_mistake (void);

自:2.32

G_UNAVAILABLE(major, minor)

此宏可以用于标记函数声明为不可用。它必须放在函数声明之前。使用带有此宏注解的函数将产生编译器警告。

自:2.32

GLIB_DISABLE_DEPRECATION_WARNINGS
一个在包含 glib.h 头文件之前应定义的宏。如果已定义,则不会产生有关已弃用 GLib API 使用的编译器警告。

版本检查

GLIB_MAJOR_VERSION

一个宏,对 GLib 版本的主成分进行求值,例如,版本 1.2.3 对应于 1

GLIB_MINOR_VERSION

一个宏,对 GLib 版本的次成分进行求值,例如,版本 1.2.3 对应于 2

GLIB_MICRO_VERSION

一个宏,对 GLib 版本的微成分进行求值,例如,版本 1.2.3 对应于 3

GLIB_CHECK_VERSION (major, minor, micro)

一个宏,当 GLib 的版本比指定的版本元组新时进行求值。