【问题标题】:Sized integers and promotions in varargs functions可变参数函数中的大小整数和提升
【发布时间】:2016-07-15 16:02:07
【问题描述】:

大小整数(来自 stdint.h 的)实际上是标准 C 类型的 typedef。因此,应用于可变参数(varargs)函数(如 printf())的“默认参数提升”也将应用于它们,以便将 char 和 short 强制转换为 int(有符号或无符号)。

我正在编写一个类似 printf 的函数,它是为大小整数设计的。它有一个格式字符串,其中包含变量参数列表中所有整数的大小信息。

我应该如何编写可变参数查询代码,以便它以正确的大小检索每个参数?我想我的函数需要知道默认参数提升,但它们是编译器/系统相关的,因为它取决于系统是否具有 16/32/64 位 int。如何以独立于编译器的方式正确获取参数?

【问题讨论】:

  • “我怎样才能以独立于编译器的方式正确地获得参数?”好吧,除了您提供的平台文档之外别无他法。
  • 其实我想我明白了。你说你不能安全地做(例如)va_arg(ap, int16_t),因为你不知道int16_tint还是short(因此它是否会被提升)。
  • @cesss:是的,我猜你可以做#if (sizeof(int16_t) < sizeof(int)) int16_t x = va_arg(ap, int); #else int16_t x = va_arg(ap, int16_t); #endif等等。
  • @Shark PromoType(v) 满足你的愿望吗?
  • @chux 是的 :)

标签: c variadic-functions


【解决方案1】:

要确定some type 是否变为intunsigned 或在传递给带有... 的函数时保持相同类型,代码可以使用_Generic()。 (C99 或更高版本)

通过使用*1,这模仿了f(format, ...) 中常见的促销活动。

现在您的 printf 类函数 可以确定参数是提升为 intunsigned 还是保持原样。

#include <stdio.h>
#define PromoType(v) _Generic(v*1, \
  unsigned : "unsigned", \
  int : "int", \
  default: "no change" \
  )

int main(void) {
  int16_t i16;
  puts(PromoType(i16));
  uint16_t u16;
  puts(PromoType(u16));
  int32_t i32;
  puts(PromoType(i32));
  uint32_t u32;
  puts(PromoType(u32));
  int64_t i64;
  puts(PromoType(i64));
  uint64_t u64;
  puts(PromoType(u64));
  return 0;
}

输出

int
int
int
unsigned
no change
no change

【讨论】:

  • 非常感谢,chux。这解决了我的问题。无论如何,我会编写几个代码路径,因为有时我需要使用可能不支持 C99 的旧编译器来构建我的代码。我找到了 typeof GCC 扩展,它可以替代它。如果编译器不支持 C99 并且也不是 GCC,我将使用上面 Oliver Charlesworth 建议的 sizeof() 方法。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-05-13
  • 2014-12-06
  • 1970-01-01
  • 2011-09-12
  • 2012-12-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多