如何在不使用强制转换的情况下打印_ExtInt?

3

我想知道如何在clang中使用_ExtInt而不使用转换来打印输出,类似于这样:

#include <stdio.h>

int main() {
    _ExtInt(13) foo = 100;
    printf("%???", foo);
}

使用强制类型转换,代码将如下所示(这不是我想要的):
#include <stdio.h>

int main() {
    _ExtInt(32) foo = 100;
    printf("%d", (int) foo);
}
2个回答

4
_ExtInt 类型是 Clang (LLVM) 的新特性,详见 2020-04-21 发布的 The New Clang _ExtInt Feature Provides Exact Bitwidth Integer Types。如果 _ExtInt(32) 是一个 32 位带符号整数类型并且 int 也是一个 32 位带符号整数类型,则可以在两次调用 printf() 时使用 %d 而不需要转换。在格式之后的参数会遵循整数提升规则,因此我预计在传递给 printf() 时,_ExtInt(13)_ExtInt(32) 都将被转换为 int,因此正确的转换说明符是 %d
如果您使用更大的类型,最多可以使用 _ExtInt(64),在任何机器上都可以使用 %lld(或者在 64 位机器上使用 %ld)。如果您使用超过这个范围的类型,那么您需要一个实现了如何处理 _ExtInt 类型的 printf(),并且这可能需要在格式中使用标记来指定长度。例如,假设它支持一个带符号的 _ExtInt(700),那么它可能会支持 %<700>d

4
看起来,这些扩展整数类型不受整数提升的影响。 - ad absurdum
我也对此感到困惑,但从文档中并没有明确说明。然而,你提供的链接页面也指出:“_实现的 _ExtInt 类型不参与任何隐式转换或整数提升..._” - ad absurdum
那是一个博客页面,不像你找到的那么精确。而且你找到的内容并没有合理地涵盖所有运算符 —— 尽管它确实指定了在像 + 这样的运算符两侧必须具有相同的大小,所以你不能在没有显式转换的情况下添加 _ExtInt(8)_ExtInt(12)。"调用约定"的注释和周围的文本暗示着 _ExtInt(13) 将被扩展为适当的较大大小(可能是16位或32位 —— 我强烈怀疑对于传统芯片来说是32位,而不是它所针对的FGPA芯片)。这两个参考资料都有很多未提及的内容。 - Jonathan Leffler
如果函数的原型声明为_ExtInt(21)(例如用于Unicode字符),那么你可以将_ExtInt(21)作为参数传递给该函数,而不能传递其他类型。_ExtInt(16)不会被隐式提升为_ExtInt(21)。但是printf()和可变参数函数要求比int更短的类型必须转换为int。要么你无法在没有强制类型转换的情况下将_ExtInt(21)传递给printf(),要么它会被提升为int(假设是32位的int)。我认为“现有的调用约定”注释意味着你可以这样做。但我还没有真正尝试过。 - Jonathan Leffler
这看起来不错,但我不确定如何为它们创建自定义的printfs... - xilpex
显示剩余3条评论

1

通过组成一个long类型的产品使用宽类型。 int可能是16位的。 long至少为32位。 long long至少为64位。

_ExtInt(13) foo1 = 100;
printf("%d\n", 1 * foo);
// or
printf("%d\n", 0 + foo);

_ExtInt(32) foo2 = 100;
printf("%ld\n", 1L * foo);
// or
printf("%ld\n", 0L + foo);

1
这似乎是避免强制类型转换的好方法;扩展整数类型可能不受整数提升的影响,但它们遵循通常的算术转换规则。 - ad absurdum
@Xilpex:你无法通过常规的printf()实现来处理_ExtInt(700)。你需要查看提供的库支持的内容,可能需要特殊的文档说明。他们可能在等待WG14(C标准委员会)提供指导。 - Jonathan Leffler

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接