当int和long在C

问题描述

让平台1的宽度为int 4个字节,宽度为long 8个字节。

让平台2的int的宽度为4个字节,long的宽度与int的宽度相同。

然后给出:

unsigned int x = 2;
long signed int y = 3;
func(x * y);

在平台1上运行时,func的第一个参数的有效类型为long signed int。这是预期的。遵循第6.3.1.1.1.4节的规定,unsigned int类型与signed int具有相同的等级。然后,根据第6.3.1.1.1.3节,signed int类型的等级比long signed int低。然后,按照第6.3.1.8.1.4.4节的要求,将乘法结果转换为long signed int类型。太好了!

在平台2上运行时,相乘的结果为long unsigned int为什么?


背景

C99标准第6.3.1.1节第1小节第3点说:

long long int的等级应大于long int的等级, 大于int的等级,大于short int的等级 signed char的等级,该等级应大于 long int

这表明,int的排名高于unsigned

此外,C99标准同一段落中的第4点表示:

任何signed整数类型的等级应等于 相应的unsigned int整数类型(如果有)。

从这里开始,有两件事是signed int类型与long unsigned int类型具有相同的等级。同样,long signed int类型与#include <stdio.h> #define func(x) _Generic((x),long unsigned int: func_longunsignedint,long signed int: func_longsignedint,signed int: func_signedint,unsigned int: func_unsignedint)(x); void func_longunsignedint (long unsigned int x) { printf("%s\t%lu\n",__func__,x); } void func_longsignedint (long signed int x) { printf("%s\t%ld\n",x); } void func_signedint (signed int x) { printf("%s\t%d\n",x); } void func_unsignedint (unsigned int x) { printf("%s\t%u\n",x); } int main(void) { printf("int width %d\n",sizeof(int)); printf("long width %d\n",sizeof(long)); unsigned int x = 2; long signed int y = -3; func(x * y); } 具有相同的排名。

最后,在第6.3.1.8节第1小节的第4.3点中说:

否则,如果具有无符号整数类型的操作数具有等级 大于或等于另一个操作数类型的等级,则 带符号整数类型的操作数将转换为 无符号整数类型的操作数。

并指出4.4:

否则,如果带符号整数类型的操作数的类型可以 用无符号整数表示操作数类型的所有值 类型,然后将无符号整数类型的操作数转换为 带符号整数类型的操作数的类型。


测试代码

gcc -m64

对于平台1,希望使用gcc -m32进行编译,以强制将long强制为8个字节,并将int为4个字节。

对于平台2,希望使用bulk_update()进行编译,以强制将long强制为4个字节,并将int为4个字节。

解决方法

我们采用unsignedlong signed int并遵循C11 6.3.1.8

  • 否则,如果带符号整数类型的操作数的类型可以表示带无符号操作数类型的所有值 整数类型,然后将转换为无符号整数类型的操作数 到带符号整数类型的操作数的类型。

在64位平台#1上,类型long signed int可以表示unsigned的所有值,因为它具有64位,而unsigned具有32位。因此unsigned会转换为long signed int

在32位平台#2上,类型long signed int不能代表unsigned的所有值(UINT_MAX=2^32而是LONG_MAX=2^31-1)。所以我们继续...

  • 否则,两个操作数都将转换为与带符号整数类型的操作数类型相对应的无符号整数类型。

...因此在平台2上,“与有符号整数类型的类型相对应的无符号整数类型”-这是long signed int + unsigned = long unsigned int。因此,在平台2上,两个操作数都转换为long unsigned int,因此您看到的结果。

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...