为什么 C 宏充当指针,即使我没有通过指针传递变量

Jon*_*Jon 1 c macros struct c-preprocessor

我正在尝试编写一系列 C 宏来为结构或管理动态分配数组的结构分组提供一些通用数据类型功能。此时,我已经为每种数据类型编写了几个结构体,并且刚刚开始编写一个宏函数,该函数可以初始化结构体变量并分配用户定义的内存量。这个想法是创建一个 init 函数,它可以初始化任何类型的结构,只要它具有 write 形式即可。对于此实现,我首先必须实例化结构的副本,然后将其传递给宏。该宏确保变量allocated_lengthactive_length的类型为size_tarray然后它通过取消引用并使用运算符来确定 的类型typeof。最后,它分配内存ptr,然后检查以确保分配没有作为NULL. 但是,在这个示例中,我没有将任何内容传递回主程序,也没有将变量作为指针传递。然而,不知何故,主程序中的结构中的结构能够看到我在宏中所做的修改。这怎么样?

#define init_vector(vec_struct, aloc_length) ({size_t _a = (aloc_length);                   \
                                  size_t _b = 0;                    \
                                  typeof(vec_struct.array) ptr = malloc(aloc_length * sizeof(&vec_struct.array));   \
                                  if (ptr == NULL) {                        \
                                    perror("WARNING: ");                        \
                                    exit(0);                                    \
                                  }                                             \
                                  vec_struct.allocated_length = _a;             \
                                  vec_struct.active_length = _b;                    \
                                  vec_struct.array = ptr;       \
                                  })
typedef struct
{
    int *array;
    size_t allocated_length;
    size_t active_length;
} IntVector;

typedef struct
{
    float *array;
    size_t allocated_length;
    size_t active_length;
} FltVector;


int main() {
    IntVector int_vec;
    init_vector(int_vec, 30);
    printf("%ld\n", int_vec.allocated_length);

    FltVector float_vec;
    init_vector(float_vec, 20);
    printf("%ld\n", float_vec.allocated_length);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

P__*_*J__ 7

您需要了解宏不是函数。它们只是在实际的 C 编译开始之前替换文本(或更精确的标记)。

编译器将编译这段代码:

int main() {
    IntVector int_vec;
    ({size_t _a = (30); size_t _b = 0; typeof(int_vec.array) ptr = malloc(30 * sizeof(&int_vec.array)); if (ptr == 
# 32 "/app/example.c" 3 4
   ((void *)0)
# 32 "/app/example.c"
   ) { perror("WARNING: "); exit(0); } int_vec.allocated_length = _a; int_vec.active_length = _b; int_vec.array = ptr; });
    printf("%ld\n", int_vec.allocated_length);

    FltVector float_vec;
    ({size_t _a = (20); size_t _b = 0; typeof(float_vec.array) ptr = malloc(20 * sizeof(&float_vec.array)); if (ptr == 
# 36 "/app/example.c" 3 4
   ((void *)0)
# 36 "/app/example.c"
   ) { perror("WARNING: "); exit(0); } float_vec.allocated_length = _a; float_vec.active_length = _b; float_vec.array = ptr; });
    printf("%ld\n", float_vec.allocated_length);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

https://godbolt.org/z/ezvKfdn33

这是你所期待的吗?

必须非常谨慎并尽可能少地使用宏。