是否可以定义一个支持所有标准(无符号)整数类型的泛型宏,以及size_t?
foo((size_t)42)只要size_t引用标准的无符号整数类型之一,就可以使用下面的示例。但是标准是否保证在任何情况下都是这种情况,或者也size_t可以指代扩展整数类型?
void foo_bool(_Bool x);
void foo_uchar(unsigned char x);
void foo_ushort(unsigned short x);
void foo_uint(unsigned x);
void foo_ulong(unsigned long x);
void foo_ullong(unsigned long long x);
#define foo(x) _Generic((x), \
_Bool: foo_bool, \
unsigned char: foo_uchar, \
unsigned short: foo_ushort, \
unsigned: foo_uint, \
unsigned long: foo_ulong, \
unsigned long long: foo_ullong)(x)
Run Code Online (Sandbox Code Playgroud)
是否可以定义支持所有标准(无符号)整数类型的类型通用宏,并且还可以
size_t?
是的 - 嵌套。
size_t 通常匹配标准整数类型,如unsigned, unsigned long, unsigned long long,但这不是C 所要求的。技巧在于如何使用_Generic何时size_t与标准类型相同以及何时不是标准类型。类似的问题也适用于uintmax_t.
void foo_size_t(size_t x) { (void)x; puts("size_t"); }
void foo_bool(_Bool x) { (void)x; puts("bool"); }
void foo_uchar(unsigned char x){ (void)x; puts("unsigned char"); }
void foo_ushort(unsigned short x){ (void)x; puts("unsigned short"); }
void foo_uint(unsigned x) { (void)x; puts("unsigned"); }
void foo_ulong(unsigned long x){ (void)x; puts("unsigned long"); }
void foo_ullong(unsigned long long x){ (void)x; puts("unsigned long long"); }
void foo_none(){ puts("TBD"); }
#define foo(x) _Generic((x), \
_Bool: foo_bool, \
unsigned char: foo_uchar, \
unsigned short: foo_ushort, \
unsigned: foo_uint, \
unsigned long: foo_ulong, \
unsigned long long: foo_ullong, \
default: foo_none)(x)
// Catch `size_t` as `size_t`
// If `size_t` is distinctive, apply the size_t function
// If `size_t` is not distinctive, others will be caught here too
#define bar(x) _Generic((x), \
size_t: foo_size_t(x), \
default: foo(x) \
)
int main(void) {
foo((float)1); // What happens when type matching nothing
foo(1lu);
foo((size_t)1);
bar((float)1); // What happens when type matching nothing
bar((size_t)1);
bar(1lu);
}
Run Code Online (Sandbox Code Playgroud)
输出
TBD
unsigned long
unsigned long // Overlap when size_t matches a type, else TBD
TBD
size_t // expect this as unsigned long if size_t was distinctive.
size_t
Run Code Online (Sandbox Code Playgroud)
请注意,创造性地使用_Generic可能会导致问题,因为对 C 的扩展仍处于萌芽阶段。