Home > Back-end >  C pointers arthmetic for arrays
C pointers arthmetic for arrays

Time:01-30

I'm reading the section on array arithmetic in K&R and came across something curious. I posted the whole paragraph for context, but I'm mainly focused on the bold part:

If p and q point to members of the same array, then relations like ==, !=, <, >=, etc. work properly. For example, p < q is true if p points to an earlier member of the array than q does. Any pointer can be meaningfully compared for equality or inequality with zero. But the behavior is undefined for arithmetic or comparisons with pointers that do not point to members of the same array. (There is one exception: the address of the first element past the end of an array can be used in pointer arithmetic.)

I got some answers here (C pointer arithmetic for arrays) but I have doubts described below:

I have a doubt in this since the following code seems to work with dereferencing and comparisons without throwing any exception or errors:

#include <stdio.h>
    
int main() {
    int a[5] = { 1, 2, 3, 4, 5 };
    int b[5] = { 1, 2, 3, 4, 5 };
    int *p = &a[7];
    int *q = &b[3];
    printf("%d\n", p);
    printf("%d\n", q);
    printf("%d\n", q > p);// relational from different arrays
    printf("%d", *p); // dereferencing also seems to work
}

Can anyone help with this?

The code should throw an error

CodePudding user response:

Your code has undefined behavior in multiple places, but the C language does not define what happens in case of undefined behavior: anything can happen. There is no exception or error to be thrown, the program may crash, produce unexected results or seem to work and produce expected results... anything goes, nothing can be expected.

There is undefined behaviour in these places:

  • int *p = &a[7]; you compute the address of a non existing element of the a array beyond the end of the array and not the element just after the end.
  • printf("%d\n", p); you pass a pointer to int where printf expects an int. You should write printf("%p\n", (void *)p);
  • printf("%d\n", q); same as above
  • printf("%d\n", q > p); using the value of p which was not initialized to a valid expression
  • printf("%d", *p); dereferencing invalid pointer p.

CodePudding user response:

You are working with undefined behavior. This means you cant rely on it - it may work well one day, may not work at all on another. But no matter what - you cant trust it.

And thats why undefined behavior is so dangerous sometimes - it may work fine until failing horribly one day with no perrior warning.

  • Related