【问题标题】:How do you printf _ExtInt without using casts?如何在不使用强制转换的情况下 printf _ExtInt?
【发布时间】:2020-08-08 17:04:40
【问题描述】:

我想知道您如何在不使用强制转换的情况下使用 clang printf _ExtInts。像这样的:

#include <stdio.h>

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

使用演员表,它看起来像这样(这不是我想要的):

#include <stdio.h>

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

【问题讨论】:

    标签: c integer printf clang extint


    【解决方案1】:

    _ExtInt 类型是 Clang (LLVM) 中的一项新功能,如 The New Clang _ExtInt Feature Provides Exact Bitwidth Integer Types 所述,于 2020 年 4 月 21 日发布(3 天前,我键入时)。

    如果 _ExtInt(32) 是 32 位有符号整数类型,而 int 是 32 位有符号整数类型,那么您可以使用 %d 并且在对 printf() 的两个调用中都没有强制转换。格式后的参数受整数提升规则的约束,所以我希望_ExtInt(13)_ExtInt(32) 在传递给printf() 时都会转换为int,因此正确的转换说明符是%d .

    如果您使用更大的类型,最多 _ExtInt(64),您可能可以在任何机器上使用 %lld(或在 64 位机器上使用 %ld)。如果你比这更大,你就靠自己了;你需要一个printf() 的实现,它知道如何处理_ExtInt 类型,并且可能会有允许指定长度的格式的符号。例如,疯狂地假设,它可能支持%&lt;700&gt;d 为签名的_ExtInt(700)

    【讨论】:

    • @exnihilo:但是文档说“一元 +-~ 运算符通常会将操作数提升为 int。在某些平台上进行这些提升会增加所需硬件的大小,因此在这些情况下,扩展整数类型不受整数提升规则的约束。”没关系;不过,我不清楚printf() 是这些运算符中的任何一个。我想这些规则适用于移位运算符,也适用于位运算符。它还说“扩展的整数类型与现有的调用约定保持一致”,我认为这意味着“它们也可以与 printf() 一起正常工作”。
    • 我也想知道,但从文档中我似乎并不清楚。然而page you linked to 还说:“实现的 _ExtInt 类型不参与任何隐式转换或整数提升,....
    • 那是一个博客页面,并不像您找到的那样精确。而且您发现的内容并没有明智地涵盖所有运算符 - 尽管它确实指定您必须在像 + 这样的运算符的任一侧具有相同的大小,因此您不能添加 _ExtInt(8) 和 @987654349 @ 没有明确的演员表。 “调用约定”注释和周围的文字暗示 _ExtInt(13) 将被延长到适当的更大尺寸(可能是 16 位或 32 位——我强烈怀疑传统芯片是 32 位,而不是它所针对的 FGPA 芯片) .两篇参考文献中都有很多内容没有说明。
    • 如果函数的原型是_ExtInt(21)(例如对于Unicode 字符),那么您就可以将_ExtInt(21) 传递给该函数,而不是其他类型。 _ExtInt(16) 不会被隐式提升为 _ExtInt(21)。但是printf() 和可变参数函数(例如)需要比int 更短的类型才能转换为int。要么你不能在没有演员表的情况下将_ExtInt(21) 传递给printf(),要么它被提升为int(假设是32 位int)。我认为“现有的调用约定”评论意味着你可以。但我还没有尝试过真实的东西。
    【解决方案2】:

    通过形成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);
    

    【讨论】:

    • 这似乎是避免演员阵容的好方法;扩展的整数类型可能不受整数提升的影响,但它们遵循通常的算术转换。
    • @Xilpex:您将无法使用printf() 的常规实现来处理_ExtInt(700)。您将不得不查看这些库提供了哪些支持——需要有特殊的文档。他们可能正在等待 WG14(标准 C 委员会)提供指导。
    猜你喜欢
    • 1970-01-01
    • 2017-10-16
    • 2013-05-23
    • 2014-09-27
    • 1970-01-01
    • 2012-07-13
    • 2019-07-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多