当int和long在C中的宽度相同时,排名有时会失败

当int和long在C中的宽度相同时,排名有时会失败,c,32bit-64bit,C,32bit 64bit,让平台1的宽度为int4字节,宽度为long8字节 让平台2具有int4字节的宽度,并且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的规定,无符号整数类型与有符号整数具有相同的等级。根据§6.3.1.1.1.3的规定,signed int类型的秩低于long

让平台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的规定,
无符号整数
类型与
有符号整数
具有相同的等级。根据§6.3.1.1.1.3的规定,
signed int
类型的秩低于
long signed int
。然后,这将触发乘法结果转换为§6.3.1.8.1.4之后的长符号int类型。太好了

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


背景

C99标准第§6.3.1.1节第1小节第3点规定:

long-long-int
的等级应大于
long-int
的等级, 应大于
int
的等级,该等级应大于
short int
的秩,应大于
签名字符

这表明,
long int
的排名高于
int

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

任何
无符号
整数类型的秩应等于 对应的有符号整数类型(如果有)

从这里可以看出,
unsigned int
类型与
signed int
类型具有相同的等级。类似地,
long unsigned int
类型与
long signed int
具有相同的等级

最后,第§6.3.1.8节第1小节第4.3点指出:

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

第4.4点:

否则,如果带符号整数类型的操作数的类型 用无符号整数表示操作数类型的所有值 类型,则具有无符号整数类型的操作数转换为 带符号整数类型的操作数的类型


测试代码

#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", __func__, x);
}

void func_signedint (signed int x)
{
    printf("%s\t%d\n", __func__, x);
}

void func_unsignedint (unsigned int x)
{
    printf("%s\t%u\n", __func__, 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);
}
#包括
#定义func(x)_泛型((x),长无符号int:func_长无符号int,长有符号int:func_长有符号int,有符号int:func_有符号int,无符号int:func_无符号int)(x);
void func_longinsignedint(长无符号整数x)
{
printf(“%s\t%lu\n”,函数x);
}
void func_longsignedint(长符号整数x)
{
printf(“%s\t%ld\n”,函数x);
}
无效函数签名(签名整数x)
{
printf(“%s\t%d\n”,函数x);
}
void func_unsignedint(unsigned int x)
{
printf(“%s\t%u\n”,函数x);
}
内部主(空)
{
printf(“整数宽度%d\n”,大小(整数));
printf(“长宽%d\n”,尺寸(长));
无符号整数x=2;
长符号整数y=-3;
func(x*y);
}
对于平台1,使用gcc-m64进行编译,希望将long强制为8字节,int强制为4字节


对于平台2,使用
gcc-m32
编译,希望将long强制为4字节,int强制为4字节。

我们采用
无符号
长符号int
,如下所示:

  • 否则,如果具有有符号整数类型的操作数的类型可以表示具有无符号整数类型的操作数类型的所有值 整数类型,则转换具有无符号整数类型的操作数 到带符号整数类型的操作数的类型
在64位平台上,1类型
长有符号整数
可以表示
无符号
的所有值,因为它有64位,而
无符号
有32位。因此,
unsigned
被转换为
long signed int

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

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

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

aa而我遗漏的一点是
长有符号int不能代表平台2上无符号的所有值。回答得好!