本文介绍了在C语言中,是否可以保证数组的起始地址小于其他元素的地址?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

换句话说,做

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 and
  • x is not greater than PTRDIFF_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语言中,是否可以保证数组的起始地址小于其他元素的地址?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-31 01:27