Cs 默认 int 类型和 <stdint.h> 的 intXX_t 类型之间的转换如何工作?
How does casting between Cs default int type and <stdint.h>'s intXX_t types work?
我正在使用 C 中使用常规旧 int
类型的代码框架,其中有很多预先存在的代码。但是,我需要编写的代码要求我使用固定长度 int32_t
。但是,我需要能够根据 int
从常规代码中获取输入,并输出到也只是常规 int
的变量。从 int32_t
到 int
的转换是否保留变量的值,或者它的特定数据表示(在这种情况下,我可能需要移位以保留值)。相反,从 int
到 int32_t
的转换会带来任何并发症吗?任何答案将不胜感激,尤其是任何一般和具体解释 stdint
库的转换约定的答案。
How does casting between Cs default int
type and <stdint.h>'s intXX_t
types work?
当 intXX_t
和 int
大小、范围和有效类型相同时,实际上没有“工作”发生。
当 intXX_t
的范围比 int
宽时,所有值都保留在新类型中。高位是符号扩展。
当 intXX_t
的范围比 int
窄时,超出范围的值将以 实现定义的 方式进行转换。这是非常常见 mod 类似环绕(低位相同)
当intXX_t
与int
的范围相同时,类型可能不同,但通常是相同的。在 select 代码中(与 _Generic
一样),区别很重要。
int
有各种尺寸和编码。
32 位(2 的补码):这很常见,尤其是在台式计算机上。
16 位(2 的补码):这在小型嵌入式处理器中很常见。
其他:包括非 2 的补码,一些 64 位图形处理器上的 64 位,一些旧机器或深奥机器上的非 2 的幂。对于 OP 的担忧,只需知道其他机器的存在,但 OP 非常 不太可能需要将代码移植到此类机器或从此类机器移植代码。
Does casting from int32_t
to int
preserve the value of the variable, or the specific data representation of it (in which case I may need to bitshift in order to preserve the value).
不需要移位。
32 位(2 的补码):将 int32_t
转换为 int
不会丢失任何值信息。在 select 情况下,可能会发生 type 变化。 int32_t
可能已定义为 long
,但 int32_t, int
更可能是完全相同的类型。
16 位(2 的补码):将 int32_t
转换为 int
会丢失信息,因为范围要小得多。在这样的机器上,最好将 int32_t
转换为 long
.
Conversely, does casting from int
to int32_t
introduce any complications?
32 位(2 的补码):不太可能出现任何问题。
16 位(2 的补码):某些情况值得审查,因为 int32_t
更宽,占用更多 space。
写得好的代码不太可能导致问题,但很多代码没有考虑可移植性。
对于 OP 的情况,我建议创建宏,而不是直接转换。由于新的工作要求,这将有助于跟踪对代码库的更改。此外,可以很容易地使用替代方案来调试范围 reduction/increase 问题。
// Use names per your coding style
#define inttoint32(i) ((int32_t) (i))
#define int32toint(i32) ((int) (i32))
我正在使用 C 中使用常规旧 int
类型的代码框架,其中有很多预先存在的代码。但是,我需要编写的代码要求我使用固定长度 int32_t
。但是,我需要能够根据 int
从常规代码中获取输入,并输出到也只是常规 int
的变量。从 int32_t
到 int
的转换是否保留变量的值,或者它的特定数据表示(在这种情况下,我可能需要移位以保留值)。相反,从 int
到 int32_t
的转换会带来任何并发症吗?任何答案将不胜感激,尤其是任何一般和具体解释 stdint
库的转换约定的答案。
How does casting between Cs default
int
type and <stdint.h>'sintXX_t
types work?
当 intXX_t
和 int
大小、范围和有效类型相同时,实际上没有“工作”发生。
当 intXX_t
的范围比 int
宽时,所有值都保留在新类型中。高位是符号扩展。
当 intXX_t
的范围比 int
窄时,超出范围的值将以 实现定义的 方式进行转换。这是非常常见 mod 类似环绕(低位相同)
当intXX_t
与int
的范围相同时,类型可能不同,但通常是相同的。在 select 代码中(与 _Generic
一样),区别很重要。
int
有各种尺寸和编码。
32 位(2 的补码):这很常见,尤其是在台式计算机上。
16 位(2 的补码):这在小型嵌入式处理器中很常见。
其他:包括非 2 的补码,一些 64 位图形处理器上的 64 位,一些旧机器或深奥机器上的非 2 的幂。对于 OP 的担忧,只需知道其他机器的存在,但 OP 非常 不太可能需要将代码移植到此类机器或从此类机器移植代码。
Does casting from
int32_t
toint
preserve the value of the variable, or the specific data representation of it (in which case I may need to bitshift in order to preserve the value).
不需要移位。
32 位(2 的补码):将
int32_t
转换为int
不会丢失任何值信息。在 select 情况下,可能会发生 type 变化。int32_t
可能已定义为long
,但int32_t, int
更可能是完全相同的类型。16 位(2 的补码):将
int32_t
转换为int
会丢失信息,因为范围要小得多。在这样的机器上,最好将int32_t
转换为long
.
Conversely, does casting from
int
toint32_t
introduce any complications?
32 位(2 的补码):不太可能出现任何问题。
16 位(2 的补码):某些情况值得审查,因为
int32_t
更宽,占用更多 space。
写得好的代码不太可能导致问题,但很多代码没有考虑可移植性。
对于 OP 的情况,我建议创建宏,而不是直接转换。由于新的工作要求,这将有助于跟踪对代码库的更改。此外,可以很容易地使用替代方案来调试范围 reduction/increase 问题。
// Use names per your coding style
#define inttoint32(i) ((int32_t) (i))
#define int32toint(i32) ((int) (i32))