处理泛型选择中的size_t

问题描述 投票:4回答:2

是否可以定义支持所有标准(无符号)整数类型的类型泛型宏,还有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)

c c11 size-t
2个回答
2
投票

是否可以定义支持所有标准(无符号)整数类型的类型泛型宏,还有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的扩展仍处于初期阶段。


1
投票

我不知道任何使用非标准类型的实现。

如果真的只有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");
© www.soinside.com 2019 - 2024. All rights reserved.