章节大纲

  • <stdarg.h> – 可变参数(Variable Arguments)

    该头文件由 C89 引入,其设计灵感来自 UNIX 的 <varargs.h>。由于标准 C 所采用的方法略有不同,因此定义了新的头文件 <stdarg.h>,而不是修改 <varargs.h> 的含义。

    C++ 注意事项:对应的标准 C++ 头文件为 <cstdarg>


    可变参数访问宏(Variable Argument List Access Macros)

    va_arg
    标准 C 要求 va_arg 是一个宏。若使用 #undef 取消宏定义并尝试使用同名函数,行为是未定义的

    va_copy
    该宏在 C99 中新增。

    标准 C 规定:“va_copy 是否为宏或具有外部链接的标识符未指定。如果屏蔽宏定义以访问实际函数,或者程序定义了同名外部标识符,则行为为未定义的。”

    va_end
    标准 C 同样规定其是否为宏或具有外部链接的标识符未指定。取消宏定义或自定义同名标识符的行为是未定义的

    va_start
    标准 C 要求它必须为宏。若取消宏定义并使用同名函数,行为为未定义的

    如果 va_start 的第二个参数使用 register 声明,或者该参数是函数或数组类型,则行为是未定义的


    <stdatomic.h> – 原子操作(Atomics)

    该头文件由 C11 引入。

    标准 C 为将来可能添加的名称保留了以下命名空间:

    • ATOMIC_ 开头、后接大写字母的宏名;

    • atomic_memory_ 开头、后接小写字母的类型名;

    • 对于 memory_order 类型,所有以 memory_order_ 开头、后接小写字母的枚举常量;

    • atomic_ 开头、后接小写字母的函数名。

    C17 弃用了宏 ATOMIC_VAR_INIT

    C++ 注意事项:标准 C++ 没有对应的头文件


    <stdbool.h> – 布尔类型和值(Boolean Type and Values)

    C99 引入了类型说明符 _Bool 及对应的头文件 <stdbool.h>,该头文件定义了以下内容:

    • 类型别名 bool

    • 宏常量 true, false

    • __bool_true_false_are_defined(表示是否已定义布尔宏)

    C++ 注意事项

    • C++11 引入 <cstdbool>,模拟 <stdbool.h> 的行为;

    • C++17 改为支持 <stdbool.h>

    • 但 C++17 同时也弃用了该头文件,因为 C++ 自带 booltruefalse 关键字。

    如何编写可移植的布尔支持代码?

    下面是一种兼容多种 C 编译器(包括不支持 <stdbool.h> 的旧版本)以及 C++ 的写法:

    #ifndef __cplusplus  // 如果是 C 编译器
        #ifndef __bool_true_false_are_defined
            #ifdef true
                #error "存在名为 >true< 的宏"
            #else
                #ifdef false
                    #error "存在名为 >false< 的宏"
                #else
                    #ifdef bool
                        #error "存在名为 >bool< 的宏"
                    #else
                        #if __STDC_VERSION__ >= 199901L
                            #include <stdbool.h> // 使用 C99 的布尔定义
                        #else
                            typedef int bool;
                            #define true 1
                            #define false 0
                            #define __bool_true_false_are_defined 1
                        #endif
                    #endif
                #endif
            #endif
        #endif
    #else  // 如果是 C++ 编译器(内建 bool/true/false)
        #ifdef true
            #error "存在名为 >true< 的宏"
        #endif
        #ifdef false
            #error "存在名为 >false< 的宏"
        #endif
        #ifdef bool
            #error "存在名为 >bool< 的宏"
        #endif
    #endif
    

    <stddef.h> – 通用定义(Common Definitions)

    C89 引入该头文件,用于集中定义一些常用宏和类型,包括:

    • 宏:NULL, offsetof

    • 类型:ptrdiff_t, size_t, wchar_t

    • C11 还添加了:max_align_t

    NULL 外,其余均为 C89 的新增内容。

    如果 offsetof 的第二个参数是位域(bit-field),行为是未定义的

    参见:C11 所附的“边界检查接口”附录可能要求实现向该头文件添加内容。

    C++ 注意事项:对应的标准 C++ 头文件为 <cstddef>


    <stdint.h> – 整数类型(Integer Types)

    该头文件由 C99 引入。

    标准 C 为将来扩展预留了以下命名规则:

    • 宏名以 INTUINT 开头,结尾为 _MAX_MIN_C

    • 类型名以 intuint 开头,结尾为 _t

    C++ 注意事项:对应的标准 C++ 头文件为 <cstdint>