有没有办法在不知道 C 语言类型的情况下将变量初始化为默认值?

Is there a way to initialize a variable to a default value without knowing its type in C?

我在玩宏,我设法做了一个可以处理任何类型的堆栈结构,但问题是 POP 函数有问题,它必须弹出值从堆栈中取出并 return 它,为此我使用了语句表达式。问题是当堆栈为空时,我必须 return 一个默认值,但我不知道变量的类型所以我不能只是 return NULLINT_MIN 因为它可以是指针、整数、数组或结构。我想要做的是将该变量初始化为默认值,如静态变量(它们自动初始化为 0{})。这是我为上下文编写的代码。 (该代码有效,但当 POP 失败时,它 return 是一个未定义的未初始化值,因此无法使用 -Wall -Wextra -Werror 编译)

#ifndef STACK_H
# define STACK_H

# include <sys/types.h>
# include <stdint.h>
# include <stdbool.h>
# include <stdlib.h>

# define STACK(type, cap) struct {\
    size_t  capacity;\
    size_t  size;\
    type    data[cap];\
}\

# define STACK_INIT(stack) \
(stack) = (typeof(stack)) {\
    .capacity = sizeof((stack).data) / sizeof(*(stack).data),\
    .size = 0,\
    .data = {}\
}

# define STACK_PUSH(stack, value) ({\
    bool    ret = true;\
\
    if ((stack).size == (stack).capacity) ret = false;\
    (stack).data[(stack).capacity - ++(stack).size] = value;\
    ret;\
})

# define STACK_POP(stack) ({\
    typeof(*(stack).data)   ret;\ // Here ret is declared
\
    if ((stack).size) ret = (stack).data[(stack).capacity - (stack).size--];\
\   // else ret is uninitialized, is it possible to give it a default value without knowing its type?
    ret;\
})

# define STACK_SIZE(stack) stack.size
# define STACK_EMPTY(stack) !stack.size

#endif

简单用法示例:

#include <stdio.h>
#include "stack.h"

int main(int argc, char **argv) {
    if (argc < 2) {
        dprintf(2, "Usage: %s <at least one argument>\n\n", argv[0]);
        return (-1);
    }
    STACK(char *, 10) stk;
    STACK_INIT(stk);
    for (int i = 1; i < argc; ++i)
        if (!STACK_PUSH(stk, argv[i])) {
            dprintf(2, "Failed to push\n\n");
            return (-1);
        }
    while (!STACK_EMPTY(stk))
        printf("%s\n", STACK_POP(stk));
    return (0);
}

我认为这在 C 中是不可能的。


但一种解决方案是假设默认值是零字节初始化的,并编写如下代码:

typeof(*(stack).data)   ret;   \
memset(&ret, 0, sizeof(ret));   \

首先。您正在使用一个非常模糊的 GCC 扩展,它允许可变长度数组作为结构成员:

# define STACK(type, cap) \
struct {                  \
    size_t  capacity;     \
    size_t  size;         \
    type    data[cap];    \
}

宏应用中:

STACK(char *, argc - 1) stk;

数组的大小将是argc-1什么是不是常量表达式。

但是,GCC 支持方便的 typeof 运算符。结合它的字面量可以使人做出:

(typeof(stack.data[0])) { 0 }

请注意 { 0 } 是适用于所有类型的通用初始化程序。 生成的对象可以分配给 data.

中所需的插槽