r值类型是否总是与C中的l值类型匹配?

问题描述 投票:0回答:2

我通过以下代码出现了一些古怪的行为:

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 overflow rvalue
2个回答
0
投票

您的编译器没有弄乱。在C中,整数文字的类型为int。使用太大的值会导致溢出,而​​由小整数值组成的表达式也会导致溢出(例如1000 * 1000 * 1000 * 1000)。如果要使代码工作,则可以使用LLL后缀表示该值应为long intlong long int类型。在特定情况下,应使用LL,因为4294967295‬超出了long int可以代表的最大值。

my_64 = 4294967295‬LL + 4294967295‬LL;

是否有任何保证r值数据类型应与l值数据类型匹配?

我认为您的意思是restrictions而不是此处的保证。通常,不,r值的类型并不总是需要与l值的类型匹配。实际上,例如,您可以使用不匹配的类型执行long long int = 1;int *ptr = 0;和其他类型的分配。自动转换在可能时完成(一个很好的例子是指向void *的任何指针的自动转换,反之亦然)。


0
投票

在此分配声明中

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类型。因此没有溢出。

© www.soinside.com 2019 - 2024. All rights reserved.