长长在 c99

如何解决长长在 c99

在 C99 标准中,他们引入了 long long。这样做的目的是什么?在我(有限的)C 编程经验中,我只见过 4 字节的 int 和 8 字节的 long。例如,从编译器资源管理器:

enter image description here

如果 long 已经是 8,为什么还需要添加一个 long long 类型?这对编译器/架构有什么影响?

解决方法

如果 long 已经是 8 了,那为什么还要再添加一个 long long 类型呢?这对编译器/架构有什么影响?

“If long is already 8”并不总是正确的,因为存在依赖 32 位 longint 作为 32 或 16 位的代码。

要求 long 为 64 位会破坏代码库。这是一个主要问题。


然而,要求 long 保持 32 位(并且没有 long long)无法访问标准的 64 位整数,因此是 long long 的基本原理。

允许 long 作为 32 位或 64 位(或其他)允许转换。

各种函数传入/返回long,如fseek(),ftell()。他们受益于 long 超过 32 位的大文件支持。

推荐的做法鼓励更广泛的 long:“用于 size_tptrdiff_t 的类型的整数转换等级不应大于 signed long int 除非实现支持足够大的对象以使其成为必要。”这与超过 32 位的内存大小有关。


也许未来的实现可能会使用 int/long/long long/intmax_t 作为 32/64/128/256 位。

IAC,我看到固定宽度类型 intN_tlonglong long 更受欢迎。我倾向于使用固定宽度类型或 bool,(unsigned) char,int/unsigned,size_t,({{1} })u 离开intmax_t,(signed char) unsigned,(short) unsigned,(long) {{ 1}} 用于特殊情况。

,

C 标准仅保证 int 可以(粗略地说)2 个字节,long 可以是 4 个字节,long long 可以是 8 个字节。

事实上,MSVC 仍然使用 4 字节的 long,即使它有一个 4 字节的 int

,

当时和现在对 intlong 的唯一相关要求是 int 必须至少为 16 位,而 long 必须至少为 32 位。 16 位和 32 位系统都倾向于使用 32 位 long,而 64 位机器在 1990 年代后期并不常见。因此,在 C99 之前,程序员根本无法轻松地依赖 64 位整数类型可用。通过引入 long long 解决了这个问题,它要求至少为 64 位。 (我相信它已经由 GCC 和其他编译器作为扩展提供了)。

如今,许多(但不是全部)64 位系统使用 64 位 long 并且不费心使 long long 变得更大,所以它是64 位也是如此,并且在某种意义上是多余的。这些大概是您熟悉的系统,但它们并不代表所有的东西。

,

我认为您没有意识到您对 C 类型宽度要求的工作方式做出了一个巨大的错误假设:ISO C 只是设置了一个最小值范围,例如允许的最小幅度LONG_MAXLONG_MIN(-2147483647,不是 8,因为 ISO C 允许一个的补码和符号/大小有符号整数,而不仅仅是 2 的补码。)实际实现允许有更广泛的类型,通常是匹配目标机器可以有效执行的寄存器宽度或操作数大小。

在 Stack Overflow 和其他地方已经写了很多关于这个的文章,我不打算在这里重复。另见https://en.cppreference.com/w/c/language/arithmetic_types


我认为,这导致您错误地查看了 x86-64 System V ABI 中的类型宽度选择并假设其他 C 实现是相同的。 x86-64 是一种 64 位 ISA,可以有效地处理 64 位整数,因此 64 位 long 是一个相当明智的选择。

对于像 i386 这样的 32 位机器,没有健全的 ABI 会使用 64 位 long,因为这不是必需的,只有 32 位。使用 64 位意味着它无法放入单个寄存器中。 使用 -m32 编译,或为 32 位 ARM 编译。 Godbolt 还具有用于 AVR 和 MSP430 的 GCC。在那些 8 位和 16 位机器上,GCC 选择 ISO C 允许的最小宽度(2 字节 int 等)

在 1999 年,x86-64 甚至不存在。 (其他一些 64 位 ISA 也这样做了,比如 Alpha)。因此,查看 2 个主流 ABI 之一以了解 C99 选择不会让您走得太远。

当然,C 需要一种保证至少为 64 位的类型,以便人们编写可以高效执行 64 位整数数学运算的程序。


顺便说一句,x86-64 可以像 64 位一样有效地处理 32 位整数,有时更有效。因此,将 long 设为 64 位类型可能不太好。一些代码使用 long 是因为他们想要一个需要是 32 位的类型,但不会因为它更宽而受益。对于此类代码,64 位 long 只会浪费缓存占用空间/内存带宽和代码大小(REX 前缀)。在 C99 中,理想的选择是 int_least32_t,但这很烦人而且很少使用。

但是 OTOH,long 有时被希望成为“最广泛有效的(1 个寄存器)类型”,尽管没有这样的保证,并且 LLP64 ABI(例如具有 32 位 long 的 Windows x64)不是'不喜欢那样。

另一个完整的蠕虫是 C99 int_fast32_t 和 x86-64 System V 的 IMO 糟糕的选择,使其成为 64 位类型。 (我对 Cpp uint32_fast_t resolves to uint64_t but is slower for nearly all operations than a uint32_t (x86_64). Why does it resolve to uint64_t? 有一个写了一半的答案,我应该完成... int_fast32_t 提出了“为了什么目的而快速”的问题,并且在许多实现中这不是您希望的案例。

另见

,

有一些限制,但编译器作者可以自由选择标准 C 变量类型(char、short、int、long、long long)的长度。自然 char 将成为该体系结构的一个字节(大多数 C 编译器是 8 位)。自然你不能让更小的东西比更大的东西更大,long 不能小于一个整数。但可以肯定的是,到 1999 年,我们看到了 x86 16 位到 32 位的转换,例如 int 从 16 位变为 32 位并使用了许多工具,但长期保持为 32。后来发生了 32 位到 64 位的 x86 转换,根据工具的不同,有可用的类型提供帮助。

问题早在此之前就存在了,解决方案不是固定类型的长度,在规则范围内,它们的大小取决于编译器作者。但是编译器作者需要制作一个与工具和目标匹配的 stdint.h 文件(stdint.h 至少是特定于工具和目标的,并且可以是该工具的工具版本和构建选项等)。因此,例如, uint32_t 始终为 32 位。一些作者会在他们的 stdint.h 中将其转换为 int 其他的 long 等。 C 语言变量类型仍然限制为每个语言的 char、short、int 等(uint32_t 不是变量类型,它通过 stdint.h 转换为变量类型)。这个解决方案/变通方法是一种防止一切变得疯狂并保持语言活跃的方法。

作者经常会选择例如 GPR 是 16 位让 int 是 16 位,如果 32 位是 32 位等等,但他们有一些自由。

是的,这特别意味着没有理由假设针对特定目标(例如您正在阅读本文的计算机)的任何两个工具对 int 和 long 使用相同的定义,特别是如果您想为这个平台编写可以跨这些工具(支持这个平台)移植的代码,然后使用 stdint.h 类型而不是 int、long 等...... arm linux 机器,一种基于 x86 的机器,类型,即使对于相同的“工具链”(例如 gnu gcc 和 binutils),对于 int 和 long 等的定义也不相同。 char 和 short 往往是 8 和16位,int和long往往变化最大,有时大小相同有时不同,但重点是不要假设。

对于编译器版本/目标/命令行选项而言,检测大小很简单,或者只是使用 stdint 路由以最大程度地减少以后的问题。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?