Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pointer arithmetic and arrays: what's really legal?

Consider the following statements:

int    *pFarr, *pVarr;

int    farr[3] = {11,22,33};
int    varr[3] = {7,8,9};

pFarr = &(farr[0]);
pVarr = varr;

At this stage, both pointers are pointing at the start of each respective array address. For *pFarr, we are presently looking at 11 and for *pVarr, 7.

Equally, if I request the contents of each array through *farr and *varr, i also get 11 and 7.

So far so good.

Now, let's try pFarr++ and pVarr++. Great. We're now looking at 22 and 8, as expected.

But now...

Trying to move up farr++ and varr++ ... and we get "wrong type of argument to increment".

Now, I recognize the difference between an array pointer and a regular pointer, but since their behaviour is similar, why this limitation?

This is further confusing to me when I also consider that in the same program I can call the following function in an ostensibly correct way and in another incorrect way, and I get the same behaviour, though in contrast to what happened in the code posted above!?

working_on_pointers ( pFarr, farr );  // calling with expected parameters
working_on_pointers ( farr, pFarr );  // calling with inverted parameters 

.

void working_on_pointers ( int *pExpect, int aExpect[] ) {

    printf("%i", *pExpect);  // displays the contents of pExpect ok
    printf("%i", *aExpect);  // displays the contents of aExpect ok

    pExpect++;               // no warnings or errors
    aExpect++;               // no warnings or errors

    printf("%i", *pExpect);  // displays the next element or an overflow element (with no errors)
    printf("%i", *aExpect);  // displays the next element or an overflow element (with no errors)

}

Could someone help me to understand why array pointers and pointers behave in similar ways in some contexts, but different in others?

So many thanks.

EDIT: Noobs like myself could further benefit from this resource: http://www.panix.com/~elflord/cpp/gotchas/index.shtml

like image 617
bitcruncher Avatar asked Dec 23 '22 05:12

bitcruncher


1 Answers

The difference is because for farr++ to have any effect, somewhere the compiler would need to store that farr will evaluate to the address of the second element of the array. But there is no place for that information. The compiler only allocates place for 3 integers.

Now when you declare that a function parameter is an array, the function parameter won't be an array. The function parameter will be a pointer. There are no array parameters in C. So the following two declarations are equivalent

void f(int *a);
void f(int a[]);

It doesn't even matter what number you put between the brackets - since the parameter really will be a pointer, the "size" is just ignored.

This is the same for functions - the following two are equivalent and have a function pointer as parameter:

void f(void (*p)());
void f(void p()); 

While you can call both a function pointer and a function (so they are used similar), you also won't be able to write to a function, because it's not a pointer - it merely converts to a pointer:

f = NULL; // error!

Much the same way you can't modify an array.

like image 98
Johannes Schaub - litb Avatar answered Jan 04 '23 21:01

Johannes Schaub - litb