jm9 jm9 - 1 month ago 6
C Question

How can I compare an array position address with a pointer addres in C?

All I want to know, is how I could do the comparison between the address of any position of the array arr and the address of the pointer c (not the address that points to). The program compiles perfectly and there are no warnings in the output, but when I execute it, the if doesn't work. I show in the program how the condition is satisfied but the printf is not executed.

#include <stdio.h>
#include <stdlib.h>

int main () {

int a = 100;
int *b = &a;
int *c = b;
int arr[5];
int i=0;

printf("\n");

printf(" a address: %p\n",&a);
printf("\n");
printf(" b address: %p\n",&b);
printf(" b points to: %p\n",b);
printf("\n");
printf(" c address: %p\n",&c);
printf(" c points to: %p\n",c);
printf("\n");
printf(" arr address: %p\n",&arr);
printf("------------------------------\n");
printf(" a value: %d\n",a);
printf(" b value: %d\n",*b);
printf(" c value: %d\n",*c);

printf("\n");
printf("------------------------------\n");
printf("\n");

printf("%p <-> ",&c); printf("%p\n",&arr[-2]);

printf("\n");


printf("Comparison: ");
if (&c==&arr[-2]) printf("OK\n");

printf("\n");
printf("\n");

for (i=-20;i<20;i++)
printf(" %4d %p %10x %15d \n",i, &arr[i],arr[i],arr[i]);

printf("\n");

// c points to a new address
arr[-2]=arr[-2]+20;

printf(" c now points to: %p\n",c);
printf(" c value: %d\n",*c);

printf("\n");

for (i=-20;i<20;i++)
if (c==&arr[i]) printf(" %4d %p %10x %15d \n",i,
&arr[i],arr[i],arr[i]);

return 0;
}

Answer

The C11 standard has this to say about &arr[-2] in section 6.5.6 par 8:

..., if the expression P points to the i -th element of an array object, the expressions (P)+N (equivalently, N+(P)) and (P)-N (where N has the value n) point to, respectively, the i+n-th and i-n-th elements of the array object, provided they exist.

Uh oh. arr[-2] does not exist if arr is a pointer to the first, or second element of an array. What happens now?

If both the pointer operand and the result point to elements of the same array object, or one past the last element of the array object, the evaluation shall not produce an overflow; otherwise, the behavior is undefined.

Oops.

So how can we make the comparison work as expected? If and only if the two operands are pointing to elements of the array, or one-past the end of the array, or one is a pointer to one-past the end of an array and the other is a pointer to the start of a different array object that happens to immediately follow the first array object in the address space. (see 6.5.9p6 for this last provision)