使用int和size_t时结果的差异

Sex*_*ast 6 c 64-bit pointers size-t 32bit-64bit

当我遇到这个例子时,我正在阅读一篇关于这里的使用size_tptrdiff_t数据类型的文章:

在此输入图像描述

代码:

int A = -2;
unsigned B = 1;
int array[5] = { 1, 2, 3, 4, 5 };
int *ptr = array + 3;
ptr = ptr + (A + B); //Error
printf("%i\n", *ptr);
Run Code Online (Sandbox Code Playgroud)

我无法理解一些事情.首先,如何添加一个signed和一个unsigned数字将输入结果转换为unsigned类型?如果结果确实0xFFFFFFFFunsigned类型,为什么在32位系统中,在添加它时ptr,是否会被解释为ptr-1,假设数字实际是unsigned类型而前导1不应该表示符号?

第二,为什么64位系统的结果不同?

有人能解释一下吗?

250*_*501 4

1. 有几件事我无法理解。首先,有符号数和无符号数相加如何将输入结果转换为无符号类型?

这是由整数提升和整数转换等级定义的。

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

在这种情况下,unsigned 的级别高于 int,因此 int 被提升为 unsigned。

int ( -2 ) 到 unsigned 的转换按如下方式执行:

6.3.1.3 p2:否则,如果新类型是无符号的,则通过比新类型可以表示的最大值重复加或减1来转换该值,直到该值在新类型的范围内

2、如果结果确实是无符号类型的0xFFFFFFFF,为什么在32位系统中,与ptr相加时,会被解释为ptr-1,因为该数字实际上是无符号类型,并且前导的1不应该表示符号?

这是未定义的行为,不应依赖它,因为 C 没有定义指针算术溢出。

6.5.6 p8:如果指针操作数和结果都指向同一个数组对象的元素,或者超过数组对象的最后一个元素,则计算不应产生溢出;否则,行为是未定义的。

3. 其次,为什么在64位系统中结果不同?

(这假设(如图所示)int 和 unsigned 是 4 个字节。)

A 和 B 的结果与1.中描述的相同,然后将该结果添加到指针。由于指针是 8 个字节,并且假设加法不会溢出(如果 ptr 有一个大地址,则仍然可能溢出,从而给出与2中相同的未定义行为),结果是一个地址。

这是未定义的行为,因为指针指向数组边界之外。