是否可以定义支持所有标准(无符号)整数类型的类型泛型宏,还有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)
是否可以定义支持所有标准(无符号)整数类型的类型泛型宏,还有
size_t
?
是的 - 有嵌套。
size_t
通常匹配像unsigned, unsigned long, unsigned long long
这样的标准整数类型,但C不需要。当_Generic
与标准类型相同且不是标准类型时,技巧变成如何使用size_t
。类似的问题适用于uintmax_t
。
void foo_size_t(_Bool 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
你担心:
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");