views:

214

answers:

6

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

+3  A: 

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.

Johannes Schaub - litb
A: 

Have a look at this answer I posted in relation to differences between pointers and arrays here on SO.

Hope this helps, Best regards, Tom.

tommieb75
A: 

Trying to increment farr or varr fails because neither one is a pointer. Each is an array. The name of an array, when evaluated by itself (except as the operand of the sizeof or address-of operator) evaluates to a value (an rvalue) that's of the correct type to be assigned to a pointer. Trying to increment it is a bit like trying to increment 17. You can increment an int that contains the value 17, but incrementing 17 itself won't work. The name of an array is pretty much like that.

As for your second part, it's pretty simple: if you attempt to declare a function parameter of array type, the compiler silently "adjusts" it to a pointer type. As such, in your working_on_pointers, aExpect and pExpect have exactly the same type. Despite the array-style notation, you've defined aExpect as having type 'pointer to int'. Since the two are the same, it's entirely expected that they'll act the same.

Jerry Coffin
A: 

you need to understand the basic concept of arrays.

when you declare an array i.e

int farr[]

you are actually declaring a pointer with this declaration

const int * farr

i.e; a "constant" pointer to integer. so when you do farr++ you are actually trying to add up to a pointer which is constant, hence compilers gives you an error.

if you need to understand, try to declare a pointer with the above declaration and you would not be able to do the arithmetic which are legal on normal pointers.

P.S: its been quiet a while i have coded in C so i am not sure about exact syntax. but bottom line is the difference between a pointer and a constant pointer.

alee
This is simply wrong -- farr is not a pointer of any kind -- its an array, the value of which can be implicitly converted to a pointer, but then its not the array (or farr) any more.
Chris Dodd
Arrays are not pointers.
Alok
+3  A: 

In C, you cannot assign to arrays. So, given:

T data[N];

where T is a type and N is a number, you cannot say:

data = ...;

Given the above, and that data++; is trying to assign to data, you get the error.

There is one simple rule in C about arrays and pointers. It is that, in value contexts, the name of an array is equivalent to a pointer to its first element, and in object contexts, the name of an array is equivalent to an array.

Object context is when you take the size of an array using sizeof, or when you take its address (&data), or at the time of initialization of an array. In all other contexts, you are in value context. This includes passing an array to a function.

So, your function:

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

is equivalent to

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

The function can't tell if it was passed an array or a pointer, since all it sees is a pointer.

There are more details in the answers to the following questions:

Also see this part of C for smarties website, which is very well-written.

Alok
i had already chosen an answer before i saw this, hope you'll settle for an upvote?
bitcruncher
@bitcruncher: No worries. As long as you understood what's happening.
Alok
A: 

okay, i may be wrong. but arrays and pointers can be used alternately.

int * ptr = (int *)malloc(2* sizeof(int));
ptr[0]=1;
ptr[1]=2;

printf ("%d\n", ptr[0]);
printf ("%d\n", ptr[1]);

here i declared a pointer and now i am treating it as array.

moreover:

As a consequence of this definition, there is no apparent difference in the behavior of the "array subscripting" operator [] as it applies to arrays and pointers. In an expression of the form a[i], the array reference "a" decays into a pointer, following the rule above, and is then subscripted just as would be a pointer variable in the expression p[i] (although the eventual memory accesses will be different, as explained in question 2.2). In either case, the expression x[i] (where x is an array or a pointer) is, by definition, identical to *((x)+(i)).

reference: http://www.lysator.liu.se/c/c-faq/c-2.html

alee
now consider the following code int arr[5] = {1,2,3,4,5}; int * ptr = arr;i just assigned the value from "arr" var to "ptr" .. .. I am not asking to explicilty copy the address of 0th element. since the name of the array is address to the first element of the array i.e the above statement is identical to int * ptr =
alee
alee
one more referece:http://www.fredosaurus.com/notes-cpp/arrayptr/26arraysaspointers.html
alee