算术转换规则
-
整型提升(Integer Promotion):
- 在进行算术运算之前,小于
int
类型的整型(如char
和short
)会被提升到int
类型。如果int
类型无法表示该值,则提升到unsigned int
。
- 在进行算术运算之前,小于
-
算术转换(Arithmetic Conversion):
- 当两个操作数的类型不同且至少有一个操作数是
unsigned long long int
时,所有操作数都被转换为unsigned long long int
类型。 - 如果操作数中有
long long int
,但没有unsigned long long int
,则所有操作数都会被转换为long long int
类型。 - 如果操作数中有
unsigned long
,但没有long long int
或unsigned long long int
,则所有操作数都会被转换为unsigned long
类型。 - 如果操作数中有
long
,但没有unsigned long
、long long int
或unsigned long long int
,则所有操作数都会被转换为long
类型。 - 如果操作数中有
unsigned int
,但没有long
、unsigned long
、long long int
或unsigned long long int
,则所有操作数都会被转换为unsigned int
类型。 - 如果操作数中只有
int
,则所有操作数都会被转换为int
类型。
- 当两个操作数的类型不同且至少有一个操作数是
关键规则
- 整型提升:较小的整型(如
char
和short
)在运算前会被提升到int
类型。 - 共同类型转换:不同类型的操作数会被转换为一个共同的类型,通常是其中范围最大的一种类型。
示例
考虑以下代码示例1:
#include <stdio.h>
int main() {
char a = 100;
unsigned long long b = 300;
unsigned long long result = a * b; // 运算过程中发生类型转换
printf("Result: %llu\n", result);
return 0;
}
解释:
-
整型提升:
a
是char
类型,会被提升到int
类型。
-
算术转换:
- 运算
a * b
中,a
提升为int
,然后int
类型的结果会被转换为unsigned long long
类型进行乘法运算。 - 最终的乘法结果是
unsigned long long
类型,存储在result
中。
- 运算
考虑以下代码示例2:
#include <stdio.h>
int main() {
char c = 100;
unsigned long long int b = c * 0xffffffffu;
unsigned long long int d = c * 0xffffffffull;
printf("%llu, %llu\n", b, d);
return 0;
}
解释
-
类型提升和运算:
char c = 100;
:c
是char
类型,值为 100。- 在算术运算之前,
c
会被提升为int
类型。因此,100
作为int
参与运算。
-
运算
c * 0xffffffffu
:0xffffffffu
是一个unsigned int
类型的常量,值为 4294967295。- 由于
c
被提升为unsigned int
类型,运算100 * 4294967295
在unsigned int
类型中进行。 - 计算结果是
429496729500
,但由于unsigned int
的范围有限(32 位),会发生溢出。溢出后的结果是429496729500 % 4294967296
,计算结果是429496729500 - 42949672960 * 10
=429496729500 - 42949672960
=4294967196
。
-
运算
c * 0xffffffffull
:0xffffffffull
是unsigned long long int
类型的常量,值为 4294967295。ull
后缀表示unsigned long long int
类型。- 运算
100 * 4294967295
在unsigned long long int
类型中进行,计算结果是429496729500
,没有溢出,因为unsigned long long int
可以表示更大的值。
-
结果存储和打印:
b
存储了unsigned int
类型运算后的溢出结果4294967196
。d
存储了unsigned long long int
类型的结果429496729500
。printf("%llu, %llu\n", b, d);
将输出b
和d
的值。
总结
b
的结果:100 * 0xffffffffu
在unsigned int
类型中计算,发生溢出,结果是4294967196
。d
的结果:100 * 0xffffffffull
在unsigned long long int
类型中计算,没有溢出,结果是429496729500
。