换句话说当做
index = &array[x] - &array[0];
是否始终保证(根据 C 标准)&array[0] <= &array[x],还是取决于编译器? 与该主题相关的 C 标准章节有哪些?
最佳答案
地址顺序是有保证的。关系运算符的行为在 C11 6.5.8p5 中定义。 :
[...] pointers to array elements with larger subscript values compare greater than pointers to elements of the same array with lower subscript values. [...]
因此 &array[x] >= &array[0]
如果 x
始终为真是元素的索引,或者比最大索引大一。 (如果 x
不是元素的索引,或者不是实际数组末尾后的索引,则行为未定义。)
但令人惊讶的是差异 &array[x] - &array[0]
定义仅当
-
x
是元素的实际索引或大于数组中最大索引的一个 and -
x
不大于PTRDIFF_MAX
因为有一个特殊的极端情况:C11 6.5.6p9说
9 When two pointers are subtracted, both shall point to elements of the same array object, or one past the last element of the array object; the result is the difference of the subscripts of the two array elements. The size of the result is implementation-defined, and its type (a signed integer type) is
ptrdiff_t
defined in the<stddef.h>
header. If the result is not representable in an object of that type, the behavior is undefined. In other words, if the expressions P and Q point to, respectively, the i-th and j-th elements of an array object, the expression (P)-(Q) has the value i-j provided the value fits in an object of typeptrdiff_t
.[...]
如果签名ptrdiff_t
与无符号 size_t
的宽度相同, 可以有一个存在索引 x
的数组大于 PTRDIFF_MAX
;然后&array[x] >= &array[0]
仍然,但是&array[x] - &array[0]
具有完全未定义的行为。
这是一个演示。我的计算机是运行 64 位 Ubuntu Linux 的 x86-64,但它也能够运行 32 位程序。在 32 位 X86 Linux + GCC 中,ptrdiff_t
是一个 32 位有符号整数,size_t
是 32 位无符号整数。在 64 位 Linux 中以 32 位模式运行的程序可以使用 malloc 轻松分配超过 2G 的内存,因为整个 4G 地址空间都保留给用户模式。
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include <stddef.h>
int main(void) {
size_t size = (size_t)PTRDIFF_MAX + 2;
size_t x = (size_t)PTRDIFF_MAX + 1;
char *array = malloc(size);
if (! array) {
perror("malloc");
exit(1);
}
array[0] = 42;
array[x] = 84;
printf("&array[0]: %p\n", (void *)&array[0]);
printf("&array[x]: %p\n", (void *)&array[x]);
printf("&array[x] >= &array[0]: %d\n", &array[x] >= &array[0]);
printf("&array[x] - &array[1]: %td\n", &array[x] - &array[1]);
printf("&array[x] - &array[0]: %td\n", &array[x] - &array[0]);
printf("(&array[x] - &array[0]) < 0: %d\n", (&array[x] - &array[0]) < 0);
}
然后为 32 位模式编译并运行:
% gcc huge.c -m32 -Wall && ./a.out
&array[0]: 0x77567008
&array[x]: 0xf7567008
&array[x] >= &array[0]: 1
&array[x] - &array[1]: 2147483647
&array[x] - &array[0]: -2147483648
(&array[x] - &array[0]) < 0: 1
内存分配成功,起始地址为0x77558008,&array[x]
在0xf7504008
, &array[x]
大于 &array[0]
.区别&array[x] - &array[1]
产生了积极的结果,而 &array[x] - &array[0]
,由于其未定义的行为,现在产生了负面结果!
关于c - 在C中,是否保证数组起始地址小于其他元素的地址?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45186243/