有没有办法在不知道 C 语言类型的情况下将变量初始化为默认值?
Is there a way to initialize a variable to a default value without knowing its type in C?
我在玩宏,我设法做了一个可以处理任何类型的堆栈结构,但问题是 POP
函数有问题,它必须弹出值从堆栈中取出并 return 它,为此我使用了语句表达式。问题是当堆栈为空时,我必须 return 一个默认值,但我不知道变量的类型所以我不能只是 return NULL
或 INT_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
.
中所需的插槽
我在玩宏,我设法做了一个可以处理任何类型的堆栈结构,但问题是 POP
函数有问题,它必须弹出值从堆栈中取出并 return 它,为此我使用了语句表达式。问题是当堆栈为空时,我必须 return 一个默认值,但我不知道变量的类型所以我不能只是 return NULL
或 INT_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
.