This post is more of a type of confirmation post rather than a particular question.
I read up some answers on this site and other places to clear up my confusion regarding pointers of type, ex- int(*)[size] which are pointers to an array. From what I've understood, there are some basic differences which I concluded on - 1) pointer arithmetic, 2) dereferencing . I wrote up this code to differentiate between int* and int(*)[size].
int arr1[5] {} ;
int (*ptr1) [5] = &arr1 ;
(*ptr1)[3] = 40 ;
cout << ptr1 << endl ;
cout << ptr1[3] << endl;
cout << ptr1 3 << endl ;
int arr2[5] {} ;
int* ptr2 = arr2 ;
ptr2[3] = 40 ;
cout << ptr2 << endl ;
cout << ptr2[3] <<endl ;
cout << ptr2 3 << endl ;
On observing the output of arithmetic on int(*)[size] its evident that when we add say i to it , it jumps over a block of 4*size*i memory whereas the int* jumps over a 4*i memory block. Also in int* the expression of the form ptr2[i] is equivalent to *(ptr2 i) but in pointers of type int(*)[size] this is not the case ptr1[i] is equivalent to (ptr1 i) and to replicate the action of ptr2[i] we have to do (*ptr1)[i] in this case.
Are there anymore significant differences between the pointers of such type and which pointer amongst them should be preferred and why ? Please correct my analysis if I have gone wrong somewhere .
CodePudding user response:
There are no differences between different kinds of pointers.
If p has the type T*, p k is the address k * sizeof(T) away from p.
If p is the location of an object that is not an array element (as is the case when you acquire it with &), p[3] and p 3 are both undefined.
(In this case, p[0] is the only well-defined indexing, and p 0 and p 1 are the only well-defined arithmetical expressions – but you're not allowed to dereference p 1.)
Your pointer-to-array code is more similar to this int* version:
int x = 0;
int* ptr2 = &x ;
ptr2[3] = 40 ;
cout << ptr2 << endl ;
cout << ptr2[3] <<endl ;
cout << ptr2 3 << endl ;
which you can probably see is Just Wrong.
CodePudding user response:
Are there anymore significant differences between the pointers of such type and which pointer amongst them should be preferred and why ?
Yes, the first snippet with ptr1[3] results in undefined behavior as you're trying to access memory(pointed by ptr1 3) that is not meant to be accessed by you.
Note that just the expression ptr1 3 is well-defined but if we try to dereference this like *(ptr1 3) or ptr1[3] then we will have undefined behavior.
Undefined behavior means anything1 can happen(from C standard's perspective) including but not limited to the program giving your expected output. But never rely on the output of a program that has undefined behavior.
On the other hand, ptr2[3] is well-defined.
1For more reading(technical definition of) on undefined behavior you can refer to undefined behavior's documentation which mentions that: there are no restrictions on the behavior of the program.

