为什么固定宽度类型委托回基元?
Why do fixed width types delegate back to primitives?
在 Visual Studio 14
中,stdint.h
header 具有固定宽度整数类型的定义,但如果您实际查看那里的定义,它们只是委托回原语。定义如下:
typedef signed char int8_t;
typedef short int16_t;
typedef int int32_t;
typedef long long int64_t;
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
typedef unsigned long long uint64_t;
那么,如果 stdint.h
所做的只是回退到基元,那么还有什么理由使用 stdint.h
吗?我也知道 Visual Studio 不只是在编译时替换这些定义,因为如果您尝试将 int8_t
打印到控制台,您将得到一个 Unicode 字符而不是数字,因为它实际上只是一个signed char
.
编辑
因为人们指出他们在逻辑上没有其他定义,所以我认为我的问题需要重述。
为什么 C++ 规范中的 header 声明它将具有 8、16、32 和 64 位固定长度的整数,并将这些整数定义为可以是任何类型的类型编译器想要的大小(以其他人在另一个问题中所说的方式 The compiler can decide that an int will a 71 bit number stored in a 128 bit memory space where the additional 57 bits are used to store the programmers girlfriends birthday.
)?
不同的平台对基元的定义不同。在一个平台上 int
可能是 16 位,而在另一个平台上它是 32 位。如果您严格依赖具有特定宽度的变量,则应使用 stdint.h
中的类型,这些类型将始终 typedef
正确地对应于当前平台上各自的原语。
So is there any reason to use stdint.h if all it does is just fallback to primitives?
它还能做什么?
header 中定义的所有 类型都可以追溯到 built-in 类型。
这个header只是给你方便,standard-defined,guaranteed-consistent别名。
针对重述的问题,不是编译器选择在高 57 位中存储生日。这是一个开发商。编译器不能对整数类型使用它想要的任何位深度。它将使用编译器开发人员告诉它使用的任何位深度,并且开发人员将根据 the requirements of the C++ standard 选择这些位深度。一旦编译器被配置和编译,位深度将不会改变1。在您更改编译器或编译器版本之前,将保证 71 位。
如果没有编译器向您抛出变量,编写好的代码已经够难了。考虑可变位深度会发生什么。在星期二的构建中一个很好的输入溢出并使一架喷气客机坠毁,因为在星期三编译器执行了一些计算并决定它永远不会看到超过 17 位的任何东西。
1 我想你可以构建一个编译器,在 运行 时间从配置文件中加载各种整数大小,但我怀疑它会使写作优化器极其复杂。
我从原始问题和重述问题中了解到,对保证宽度整数(我说保证是因为并非 stdint.h
中的所有类型都具有固定宽度)和它们解决的实际问题存在误解。
C/C++ 定义基元,例如 int
、long int
、long long int
等。为简单起见,让我们关注最常见的基元,即 int
. C 标准定义的是 int
应该至少为 16 位宽。但是,在所有广泛使用的 x86 平台上的编译器实际上会在您定义 int
时为您提供一个 32 位宽的整数。发生这种情况是因为 x86 处理器可以直接从内存中获取一个 32 位宽的字段(字大小为 32 位 x86 CPU),将其按原样提供给 ALU 以进行 32 位运算并将其存储回内存,而无需必须做任何班次、填充等,这非常快。但并非每个 compiler/architecture 组合都是如此。如果您在嵌入式设备上工作,例如使用非常小的 MIPS 处理器,当您定义 int
时,您可能会从编译器获得一个 16 位宽的整数。 因此,基元的宽度由编译器指定,完全取决于目标平台的硬件功能,相对于标准定义的最小宽度。是的,在一个奇怪的架构上例如一个 25 位 ALU,你可能会得到一个 25 位 int
.
为了让一段 C/C++ 代码可以在许多不同的 compiler/hardware 组合中移植,stdint.h
提供了保证一定宽度(或最小宽度)的类型定义。所以,例如当你想使用一个 16 位有符号整数时(例如为了节省内存,或 mod-counters),你不必担心你是否应该使用 int
或 short
,只需使用 int16_t
。 编译器的开发人员将为您提供一个正确构造的 stdint.h
,它将请求的固定大小整数定义为实现它的实际原语。 这意味着,在 x86 上 int16_t
可能会被定义为 short
,而在小型嵌入式设备上,您可能会得到 int
,所有这些映射都由编译器的开发人员维护。
在 Visual Studio 14
中,stdint.h
header 具有固定宽度整数类型的定义,但如果您实际查看那里的定义,它们只是委托回原语。定义如下:
typedef signed char int8_t;
typedef short int16_t;
typedef int int32_t;
typedef long long int64_t;
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
typedef unsigned long long uint64_t;
那么,如果 stdint.h
所做的只是回退到基元,那么还有什么理由使用 stdint.h
吗?我也知道 Visual Studio 不只是在编译时替换这些定义,因为如果您尝试将 int8_t
打印到控制台,您将得到一个 Unicode 字符而不是数字,因为它实际上只是一个signed char
.
编辑
因为人们指出他们在逻辑上没有其他定义,所以我认为我的问题需要重述。
为什么 C++ 规范中的 header 声明它将具有 8、16、32 和 64 位固定长度的整数,并将这些整数定义为可以是任何类型的类型编译器想要的大小(以其他人在另一个问题中所说的方式 The compiler can decide that an int will a 71 bit number stored in a 128 bit memory space where the additional 57 bits are used to store the programmers girlfriends birthday.
)?
不同的平台对基元的定义不同。在一个平台上 int
可能是 16 位,而在另一个平台上它是 32 位。如果您严格依赖具有特定宽度的变量,则应使用 stdint.h
中的类型,这些类型将始终 typedef
正确地对应于当前平台上各自的原语。
So is there any reason to use stdint.h if all it does is just fallback to primitives?
它还能做什么?
header 中定义的所有 类型都可以追溯到 built-in 类型。
这个header只是给你方便,standard-defined,guaranteed-consistent别名。
针对重述的问题,不是编译器选择在高 57 位中存储生日。这是一个开发商。编译器不能对整数类型使用它想要的任何位深度。它将使用编译器开发人员告诉它使用的任何位深度,并且开发人员将根据 the requirements of the C++ standard 选择这些位深度。一旦编译器被配置和编译,位深度将不会改变1。在您更改编译器或编译器版本之前,将保证 71 位。
如果没有编译器向您抛出变量,编写好的代码已经够难了。考虑可变位深度会发生什么。在星期二的构建中一个很好的输入溢出并使一架喷气客机坠毁,因为在星期三编译器执行了一些计算并决定它永远不会看到超过 17 位的任何东西。
1 我想你可以构建一个编译器,在 运行 时间从配置文件中加载各种整数大小,但我怀疑它会使写作优化器极其复杂。
我从原始问题和重述问题中了解到,对保证宽度整数(我说保证是因为并非 stdint.h
中的所有类型都具有固定宽度)和它们解决的实际问题存在误解。
C/C++ 定义基元,例如 int
、long int
、long long int
等。为简单起见,让我们关注最常见的基元,即 int
. C 标准定义的是 int
应该至少为 16 位宽。但是,在所有广泛使用的 x86 平台上的编译器实际上会在您定义 int
时为您提供一个 32 位宽的整数。发生这种情况是因为 x86 处理器可以直接从内存中获取一个 32 位宽的字段(字大小为 32 位 x86 CPU),将其按原样提供给 ALU 以进行 32 位运算并将其存储回内存,而无需必须做任何班次、填充等,这非常快。但并非每个 compiler/architecture 组合都是如此。如果您在嵌入式设备上工作,例如使用非常小的 MIPS 处理器,当您定义 int
时,您可能会从编译器获得一个 16 位宽的整数。 因此,基元的宽度由编译器指定,完全取决于目标平台的硬件功能,相对于标准定义的最小宽度。是的,在一个奇怪的架构上例如一个 25 位 ALU,你可能会得到一个 25 位 int
.
为了让一段 C/C++ 代码可以在许多不同的 compiler/hardware 组合中移植,stdint.h
提供了保证一定宽度(或最小宽度)的类型定义。所以,例如当你想使用一个 16 位有符号整数时(例如为了节省内存,或 mod-counters),你不必担心你是否应该使用 int
或 short
,只需使用 int16_t
。 编译器的开发人员将为您提供一个正确构造的 stdint.h
,它将请求的固定大小整数定义为实现它的实际原语。 这意味着,在 x86 上 int16_t
可能会被定义为 short
,而在小型嵌入式设备上,您可能会得到 int
,所有这些映射都由编译器的开发人员维护。