C 类型如何保证位宽度?

C 类型如何保证位宽度?,c,linker,compiler-construction,C,Linker,Compiler Construction,既然C是一种松散类型的语言,并且我假设stdint.h只定义typedef,那么如何保证int的宽度呢 我要问的是实现,而不是库的使用。stdint.h是C实现的一部分,它使用适合于该实现的任何底层类型定义typedef。它不是一个可移植的文件,您可以将它携带到任何您喜欢的C实现中。stdint.h是C实现的一部分,它使用适合于该实现的任何底层类型定义TypeDef。它不是一个可移植的文件,您可以将其携带到任何您喜欢的C实现中 类型如何保证位宽度 C不能也不需要它 C不需要最小宽度 下面的“个性

既然C是一种松散类型的语言,并且我假设stdint.h只定义typedef,那么如何保证int的宽度呢

我要问的是实现,而不是库的使用。

stdint.h是C实现的一部分,它使用适合于该实现的任何底层类型定义typedef。它不是一个可移植的文件,您可以将它携带到任何您喜欢的C实现中。

stdint.h是C实现的一部分,它使用适合于该实现的任何底层类型定义TypeDef。它不是一个可移植的文件,您可以将其携带到任何您喜欢的C实现中

类型如何保证位宽度

C不能也不需要它

C不需要最小宽度

下面的“个性”仅在支持个性的系统上需要,符号类型不需要填充和2的补码

(u)int8_t, (u)int16_t, (u)int32_t, (u)int64_t
一个实现可以选择具有其他大小,如uint24\t

以下是必需的

(u)int_least8_t, (u)int_least16_t, (u)int_least32_t, (u)int_least64_t
类型如何保证位宽度

C不能也不需要它

C不需要最小宽度

下面的“个性”仅在支持个性的系统上需要,符号类型不需要填充和2的补码

(u)int8_t, (u)int16_t, (u)int32_t, (u)int64_t
一个实现可以选择具有其他大小,如uint24\t

以下是必需的

(u)int_least8_t, (u)int_least16_t, (u)int_least32_t, (u)int_least64_t

C编译器最终需要编译成机器代码。机器代码只有硬的、固定宽度的类型,如32位int、64位int等。或者更确切地说,它有该大小的内存块+操作,这些操作在该大小的内存上运行,并将其视为有符号或无符号

因此,创建编译器的人定义了编译器在请求int时实际使用的内容,而stdint.h头文件是他们编写的文件。它基本上是记录他们所做的事情。他们知道,例如,他们的长类型大小为64位,因此添加一个typedef long int64\t;等等

在int为16位、long为32位的系统上,他们甚至可以让编译器理解一种特殊的内部类型,例如,将其命名为u int64,然后使stdint.h包含一个typedef u int64 int64

C标准只是定义了编译器必须提供一个stdint.h头,如果在其中定义int64_t,它必须映射到正确大小的数据类型


理论上,我们可以将stdint.h中的所有内容构建到编译器中,而不是使用像u int64这样的中间名称并将其类型定义为int64,他们可以直接使用int64,但是通过使用这种方法,在stdint.h之前编写并定义了自己的类型int64_t的旧代码不能包含stdint,因此将继续编译。历史上,以两个下划线开头的名称一直是编译器制造商保留的,因此现有的C代码不可能已经使用名称_int64。

C编译器最终需要编译为机器代码。机器代码只有硬的、固定宽度的类型,如32位int、64位int等。或者更确切地说,它有该大小的内存块+操作,这些操作在该大小的内存上运行,并将其视为有符号或无符号

因此,创建编译器的人定义了编译器在请求int时实际使用的内容,而stdint.h头文件是他们编写的文件。它基本上是记录他们所做的事情。他们知道,例如,他们的长类型大小为64位,因此添加一个typedef long int64\t;等等

在int为16位、long为32位的系统上,他们甚至可以让编译器理解一种特殊的内部类型,例如,将其命名为u int64,然后使stdint.h包含一个typedef u int64 int64

C标准只是定义了编译器必须提供一个stdint.h头,如果在其中定义int64_t,它必须映射到正确大小的数据类型


理论上,我们可以将stdint.h中的所有内容构建到编译器中,而不是使用像u int64这样的中间名称并将其类型定义为int64,他们可以直接使用int64,但是通过使用这种方法,在stdint.h之前编写并定义了自己的类型int64_t的旧代码不能包含stdint,因此将继续编译。历史上,以两个下划线开头的名称一直是编译器生成器保留的,因此现有的C代码不可能已经使用名称uu int64。

因此编译器应该将这些名称理解为int等本机类型,特别是对于那些类型。对吗?@nikoss,我不知道你说的魔法是什么意思。需要指出的一点是,编译器是在规范规定的限制范围内决定int等类型的实际宽度的编译器,因此如果类型为
e在ABI中约定,则编译器甚至无需提供;库和/或头实现可以是独立的,并且仍然具有正确的类型,因为它们是在ABI中设置的。是的,他们的决定可能受到架构和/或操作系统ABI等其他因素的严重影响。@ikegami:我不是反对你所说的;我只是觉得这是一个常见的困惑,看看最近的一篇文章“实施”是什么意思?当通用系统有来自不同方面的编译器、链接器、内核、std库等时,这些边界在哪里的问题,需要理解的缺失因素是它们都同意一些ABI合同。因此,编译器应该将它们理解为诸如int之类的本机类型,特别是对于那些类型。对吗?@nikoss,我不知道你说的魔法是什么意思。需要指出的是,编译器是在规范规定的范围内决定int等类型的实际宽度的编译器,因此编译器能够提供合适的stdint。此外,如果类型在ABI中达成一致,则编译器甚至不需要提供;库和/或头实现可以是独立的,并且仍然具有正确的类型,因为它们是在ABI中设置的。是的,他们的决定可能受到架构和/或操作系统ABI等其他因素的严重影响。@ikegami:我不是反对你所说的;我只是觉得这是一个常见的困惑,看看最近的一篇文章“实施”是什么意思?当公共系统有来自不同方面的编译器、链接器、内核、std库等时,这些边界在哪里?需要理解的缺失因素是,存在一些他们都同意的ABI合同。