我通过以下代码出现了一些古怪的行为:
uint64_t my_64;
my_64 = 4294967295 + 4294967295;
我希望my_64
的结果为8589934590
,但是,我得到了另一个数字。
我的理论是,我的编译器将值存储为32位整数,因此在将其赋给变量之前会导致溢出。如果执行以下操作,则会得到预期的答案:
uint64_t my_64;
my_64 = 4294967295;
my_64 =+ 4294967295;
是否有任何保证r值数据类型应与l值数据类型匹配?还是我的编译器搞砸了?
您的编译器没有弄乱。在C中,整数文字的类型为int
。使用太大的值会导致溢出,而由小整数值组成的表达式也会导致溢出(例如1000 * 1000 * 1000 * 1000
)。如果要使代码工作,则可以使用L
或LL
后缀表示该值应为long int
或long long int
类型。在特定情况下,应使用LL
,因为4294967295
超出了long int
可以代表的最大值。
my_64 = 4294967295LL + 4294967295LL;
是否有任何保证r值数据类型应与l值数据类型匹配?
我认为您的意思是restrictions而不是此处的保证。通常,不,r值的类型并不总是需要与l值的类型匹配。实际上,例如,您可以使用不匹配的类型执行long long int = 1;
,int *ptr = 0;
和其他类型的分配。自动转换在可能时完成(一个很好的例子是指向void *
的任何指针的自动转换,反之亦然)。
在此分配声明中
my_64 = 4294967295 + 4294967295;
my_64的左值的类型与右侧操作数的右值的类型相同。编译器使用常规的算术转换来确定赋值之前的通用类型。
问题是此子表达式的操作数
4294967295 + 4294967295
具有类型int。并且操作数的常见类型也是int类型。因此确实存在溢出。然后将溢出的结果转换为uint64_t类型。
至此声明
my_64 =+ 4294967295;
^^^
有错字。我确定你的意思是
my_64 += 4294967295;
然后从逻辑上来说,它的评估方式是
my_64 = my_64 + 4294967295;
在这种情况下,子表达式的第二个操作数
my_64 + 4294967295
转换为uint64_t类型。因此没有溢出。