在一般选择中处理 size_t
Handling size_t in a generic selection
是否可以定义一个支持所有标准(无符号)整数类型的泛型宏,size_t
?
只要 size_t
指的是一种标准无符号整数类型,foo((size_t)42)
就可以与下面的示例一起使用。但是标准是否保证任何地方都是这种情况,或者 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)
我不知道有任何为此使用非标准类型的实现。
如果真的只是size_t
你担心:
- 你可以有一个
foo_size
函数并把它放在 default
条款。
- 如果
size_t
不在其中,您可以使用编译测试来排除错误
标准无符号类型。
类似
static_assert(
_Generic(sizeof(int),
unsigned char: 1,
unsigned short: 1,
...
unsigned long long, 1,
default: 0),
"size_t not among the standard unsigned types");
Is is possible to define a type-generic macro that supports all standard (unsigned) integer types, and also size_t
?
是 - 有嵌套。
size_t
通常 匹配像 unsigned, unsigned long, unsigned long long
这样的标准整数类型,但 C 并不 要求 . 诀窍变成了当 size_t
与标准类型相同时以及当它不是标准类型时如何使用 _Generic
。类似的问题适用于 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);
}
输出
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
请注意 创造性 使用 _Generic
可能会导致问题,因为对 C 的扩展仍处于初期阶段。
是否可以定义一个支持所有标准(无符号)整数类型的泛型宏,size_t
?
size_t
指的是一种标准无符号整数类型,foo((size_t)42)
就可以与下面的示例一起使用。但是标准是否保证任何地方都是这种情况,或者 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)
我不知道有任何为此使用非标准类型的实现。
如果真的只是size_t
你担心:
- 你可以有一个
foo_size
函数并把它放在default
条款。 - 如果
size_t
不在其中,您可以使用编译测试来排除错误 标准无符号类型。
类似
static_assert(
_Generic(sizeof(int),
unsigned char: 1,
unsigned short: 1,
...
unsigned long long, 1,
default: 0),
"size_t not among the standard unsigned types");
Is is possible to define a type-generic macro that supports all standard (unsigned) integer types, and also
size_t
?
是 - 有嵌套。
size_t
通常 匹配像 unsigned, unsigned long, unsigned long long
这样的标准整数类型,但 C 并不 要求 . 诀窍变成了当 size_t
与标准类型相同时以及当它不是标准类型时如何使用 _Generic
。类似的问题适用于 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);
}
输出
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
请注意 创造性 使用 _Generic
可能会导致问题,因为对 C 的扩展仍处于初期阶段。