问题描述
换句话说,做
index = &array[x] - &array[0];
是否始终(按照C标准)保证& array [0]< =& array [x],还是取决于编译器?与该主题相关的C标准章节是什么?
Is it always guaranteed (per C standard) that &array[0] <= &array[x], or is it dependent on the compiler?What are the C standard chapters relevant for this topic ?
推荐答案
保证地址顺序.关系运算符的行为在 C11 6.5.8p5 :
The address ordering is guaranteed. The behaviour of relational operators is defined in C11 6.5.8p5:
因此,如果x
是元素的索引或大于最大索引的元素,则&array[x] >= &array[0]
始终为true. (如果x
不是元素的索引,也不是实际数组末尾的索引,则行为是不确定的.)
Thus &array[x] >= &array[0]
is true always if x
is the index of an element, or one greater than the maximum index. (And if x
is not the index of an element, or one past the end of the actual array, then behaviour is undefined.)
但是令人惊讶的是,差异 &array[x] - &array[0]
仅在
时定义,当
But surprisingly the difference &array[x] - &array[0]
is defined only when
-
x
是元素的实际索引,或者比数组和 中的最大索引大一个 -
x
不大于PTRDIFF_MAX
x
is an actual index of an element or one greater than the maximum index in the array andx
is not greater thanPTRDIFF_MAX
因为有一个特殊的极端情况: C11 6.5.6p9 表示
as there is a peculiar corner case: C11 6.5.6p9 says that
如果带符号的ptrdiff_t
与未带符号的size_t
具有相同的宽度,则可能有一个数组,该数组的索引x
大于PTRDIFF_MAX
;那么&array[x] >= &array[0]
仍然,但是&array[x] - &array[0]
完全没有定义的行为.
If the signed ptrdiff_t
is of same width as the unsigned size_t
, it is possible to have an array for which there exists an index x
greater than PTRDIFF_MAX
; then &array[x] >= &array[0]
still, but &array[x] - &array[0]
has completely undefined behaviour.
这是一个示范.我的计算机是运行64位Ubuntu Linux的x86-64,但它也能够运行32位程序.在32位X86 Linux + GCC中,ptrdiff_t
是32位有符号整数,而size_t
是32位无符号整数.在64位Linux上以32位模式运行的程序可以轻松地使用malloc分配超过2G的内存,因为整个4G地址空间都是为用户模式保留的.
Here is a demonstration. My computer is x86-64 that runs 64-bit Ubuntu Linux, but it is also capable of running 32-bit programs. In 32-bit X86 Linux + GCC, ptrdiff_t
is a 32-bit signed integer, and size_t
is 32-bit unsigned integer. A program run in 64-bit Linux in 32-bit mode can easily allocate over 2G of memory with malloc, as the entire 4G address space is reserved for user mode.
#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位模式并运行:
Then compiled for 32-bit mode and run:
% 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]
具有不确定的行为,现在却产生了消极的结果!
The memory was allocated successfully, the starting address is at 0x77558008, &array[x]
is at 0xf7504008
, &array[x]
is greater than &array[0]
. The difference &array[x] - &array[1]
produced a positive result, whereas &array[x] - &array[0]
, with its undefined behaviour, now produced a negative result!
这篇关于在C语言中,是否可以保证数组的起始地址小于其他元素的地址?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!