In other word when doing
index = &array[x] - &array[0];
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 ?
Arrays a kind of data structure that can store a fixed-size sequential collection of elements of the same type. An array is used to store a collection of data, but it is often more useful to think of an array as a collection of variables of the same type.
int reqArraySize; printf("Enter the array size: "); scanf("%d", &reqArraySize); After this you may proceed with this interger input array size : for(i=0;i<reqArraySize;i++) scanf("%d",&arr[i]);
When you have created an array the first element in the array is referred to as a[0], the first memory address of the array.
Accessing array elements greater than its size If you try to access the array position (index) greater than its size, the program gets compiled successfully but, at the time of execution it generates an ArrayIndexOutOfBoundsException exception.
The address ordering is guaranteed. The behaviour of relational operators is defined in 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. [...]
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.)
But surprisingly the difference &array[x] - &array[0]
is defined only when
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
as there is a peculiar corner case: C11 6.5.6p9 says that
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
.[...]
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.
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);
}
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
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!
First of all, FWIW, quoting C11
, chapter §6.5.6/P9, (emphsis mine)
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. [...]
So, you don't need to be bothered about the individual pointer value (positioning) itself. It's the difference that matters (i.e, something like |a-b|
)
That said, if it has to come to the "comparison", ( usage of relational operators, <
, >
, <=
, >=
), the standard says,
When two pointers are compared, the result depends on the relative locations in the address space of the objects pointed to. [....] If the objects pointed to are members of the same aggregate object, [...] and pointers to array elements with larger subscript values compare greater than pointers to elements of the same array with lower subscript values. [....]
So, for a statement like &array[x] <= &array[0]
, it will evaluate to 0
(FALSY), when x > 0
.
Thanks to the other answer by Joachim
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With