问题描述
以下代码通过将 long long int
类型的变量分配给 int64_t
类型的变量,将 long long int
类型的值转换为 int64_t
类型的值。这种将 long long int
转换为 int64_t
的方法有哪些潜在问题?
#include <stdio.h>
#include <stdint.h>
int main (void) {
long long int num = 9223372036854775807; // 2^63-1
int64_t num64_t = num;
printf("%lld\n",num64_t);
return 0;
}
一个问题可能是 ISO/IEC 9899:1999 standard 在 p 上指定。 22,§ 5.2.4.2.1,long long int
的范围至少 ±2^63-1,而 int64_t
类型恰好 em> 64 位宽度。可能是在某些机器上使用超过 64 位存储 long long int
类型的值吗?如果 num
的值大于 2^63-1 或小于 -(2^63-1),这可能会导致上述程序崩溃,因为 num64_t
只有 64 位可用。
如果这是一个问题:还有其他问题吗?更一般地说:上述方法是将 long long int
类型的值转换为 int64_t
类型的值的安全方法吗?如果没有,如何避免这些问题?
解决方法
一个问题可能是 ISO/IEC 9899:1999 标准在 p. 上指定。 22,§ 5.2.4.2.1,long long int
的范围至少 ±2^63-1,而 int64_t 类型恰好 64位宽度。
C99 已过时,但该标准的最新版本(当前为 C2017)指定了相同的内容。是的,这是一个潜在的问题:与其说是类型的大小,不如说是它们的可表示值的范围。如果您尝试将 long long int
值分配给 int64_t
,并且该值不能表示为 int64_t
,那么结果要么是实现定义的,要么引发实现定义的信号.
会不会是在某些机器上使用超过 64 位存储 long long int 类型的值?
是的,这是可能的。而且long long int
的范围比int64_t
的范围更广。
如果 num
的值大于 2^63-1 或小于 -(2^63-1),这可能会导致上述程序崩溃,因为 num64_t
只有 64 位可用。
是的,如果结果是发出信号,则可能会导致程序崩溃。然而,更典型的情况是,转换成功但(必然)在受让人中产生了不同的价值。这可以说更糟,因为您没有立即注意到问题。
如果这是一个问题:还有其他问题吗?更一般地说:上述方法是否是将 long long int
类型的值转换为 int64_t
类型的值的安全方法?
将整数值分配给任何整数类型的对象都会自动将该值转换为目标类型。当分配的值可在目标类型中表示时,允许从一种整数类型转换为另一种类型并保留值。尽管与您的具体情况无关,但如果目标类型是无符号的,则允许并明确定义此类转换,即使原始值在无符号目标类型中无法表示。我已经描述了所有其他情况下的效果。
也就是说,不,除了已经描述的尝试将超出范围的值分配给目标有符号整数对象的后果之外,没有需要担心的问题。