Can someone explain why I can do:
int x[4] = { 0, 1, 2, 3 };
int *p = x;
But cannot do:
int x[2][2] = { 0, 1, 2, 3 };
int **p = x;
Is there a way to be able to assign to **p the x[][]?
TIA
A pointer to int int * can point at an integer within an array of integers, so that's why the first is OK;
int x[4] = { 0, 1, 2, 3 };
int *p = x;
This makes p point to x[0], the first int in x.
A pointer to a pointer-to-int int ** can point at a pointer-to-int within an array of pointers-to-int. However, your second array is not an array of pointers-to-int; it is an array of arrays. There are no pointers-to-int, so there is nothing sensible to point int **p at. You can solve this in two ways. The first is to change the type of p so that it is a pointer-to-array-of-2-ints:
int x[2][2] = { 0, 1, 2, 3 };
int (*p)[2] = x;
Now p points at x[0], the first int [2] in x.
The alternative is to create some pointers-to-int to point at:
int x[2][2] = { 0, 1, 2, 3 };
int *y[2] = { x[0], x[1] };
int **p = y;
Now p points at y[0], which is the first int * in y. y[0] in turn points at x[0][0], and y[1] points at x[1][0].
Using the pointer notation you can do this
*(p + n) will return back a value in the subscript n which is equivalent of
p[n], a "single dimension array"
*( * (p + i) + j) will return back a value in the subscripts i and j which
is equivalent of p[i][j], a "double dimension array"
This will prove that using array subscripts [] decays into pointers as per the rule - see ANSI C Standard, 6.2.2.1 - "An array name in an expression is treated by the compiler as a pointer to the first element of the array", furthermore, ANSI C Standard 6.3.2.1 - "A subscript is always equivalent to an offset from a pointer", and also ANSI C Standard 6.7.1 - "An array name in the declaration of a function parameter is treated as a pointer to the first element in the array"
If you are not sure in understanding how pointers and arrays work, please see my other answer which will explain how it works...
Please ignore anyone who says arrays and pointers are the same - they are not...
No, there's no way to assign the array to an "int **", because a two-dimensional array is an array of arrays, not an array of pointers.
You could for instance do:
int x1[2] = {0, 1};
int x2[2] = {2, 3};
int *x[2] = {x1, x2};
int **p = x;
... and maybe that would be an acceptable equivalent to what you are trying to do (depending on what exactly that is of course!).
Update: If you must keep x as a two-dimensional array, you could also do: int (*p)[2] = x; which gives you a pointer-to-array-of-int.
There is no way to meaningfully initialize you variable p with x. Why? Well, there's no way to answer your question until you explain how you even came to this idea. The type of p is int **. The type of x is int[2][2]. These are two different types. Where did you get the idea that you should be able to assign one to the other?
If you really need to access elements of your x through a pointer of type int **, you have to do it indirectly. You have to create an additional intermediate array that will hold pointers to first elements of consecutive rows of array x:
int *rows[2] = { x[0], x[1] };
and now you can point your p to the beginning of this intermediate array
int **p = rows;
Now when you assess p[i][j] you get x[i][j].
There's no way to do it directly, without an intermediate array.
If you are really using c++ instead of c, you can get this effect by using std::vector (or some other collection type).
typedef std::vector<std::vector<int> > intmatrix;
intmatrix x;
intmatrix::iterator p = x.begin();
or some such.
It's all about Standard Conversion rule ($4.2)
An lvalue or rvalue of type “array ofN
T” or “array of unknown bound of T”
can be converted to an rvalue of type
“pointer to T.” The result is a
pointer to the first element of the
array.
The type of od and td respectively are
char [3]
char [1][3]
This means that od has type 'array of 3 chars' (N = 3, T = char).
So in accordance with the above quote, it can be converted to 'pointer to char'
Therefore char *p = od; is perfectly well-formed
Similarly the type of od is 'array of 1 array of 3 chars' (N = 1, T = array of 3 chars).
So in accordance with the above quote, it can be converted to 'pointer to array of 3 chars'
Therefore char (*p)[3] = td; is perfectly well-formed
Is there a way to be able to assign to
**p the x[][]?
No. Because type of td[x][y] for valid x and y is char. So what you can really do is char *pc = &td[0][0].
Related
I'm learning about pointers:
int x[10];
int *p = &x
this would make a pointer type int to the first element. So, if I had 2D array, I need to use double pointer: first pointer would point to the second dimension of the array. This means :
int x[3][4] = {{1,2,3,4},{5,6,7,8},{9,9,9,9}};
and when I want to point to it I must declare the size of the second dimension like this, right ?
int *p[4] = x;
or there is another way by typing : int **p; ?
and int *p[4] is array of integer pointers which takes 4 * (sizeof(int*)), right?
this would make a pointer type (int) to first element ..
No.
&x is the address of array x and is of type int (*)[10] and you can't assign it to a int * type. Both are incompatible types.
So, if I had 2D array, I need to use double pointer: first pointer would point to the second dimension of the array.
No.
In expressions, arrays converted to pointer to its first elements except when an operand of sizeof and unary & operator. Therefore, in this case the type of x will be int (*)[4] after conversion. You need a pointer to an array of 4 int instead of an array of 4 pointers
int (*p)[4] = x;
To add, the first example is not correct.
x is an array of 10 ints. p is a pointer to int and not a pointer to an array of 10 ints. When assigned to p, x decays to the type pointer to int.
The assignment should be simply:
int* p = x;
Example program:
#include <stdio.h>
main(int argc, char* argv[])
{
int x[3][4] = { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 987, 9, 9 } };
int(*p)[4] = x; printf("p[2][1] %d", p[2][1]);
printf("\nsizeof(p) is : %d \nsizeof(*p) is : %d\n", sizeof(p), sizeof(*p));
}
Output
p[2][1] 987
sizeof(p) is : 4
sizeof(*p) is : 16
In my system (as in yours) int and pointers are 32 bits. So the size of a pointer is 4 and the size of an int is 4 too.
p is a pointer first of all. Not an array. A pointer. It's size is 4 no less no more. That's the answer to your question
Now, just to add some useful information:
p is a pointer to an array of 4 integers. The size of what p points to is 4*4==16. (Try to change int to short in the example program, you'll have sizeof(*p) is : 8)
I can assign p=x because the type is correct, now p contains the address of x and p[0] is the same as x[0] (the same array of 4 int). p[2][3] is the same as x[2][3] and *(p[2]+3). p[2] points to the element 2 of x and p[2]+3 points to the element 3 of x[2]. (all indexing is 0 based)
// Here is not complicated matrix of size
int p[2][4]={
{1,2,3,4},
{5,6,7,8}
};
// points to the first Elements :: ptr
int (*ptr)[0] = &p;
// Now have the same adresse ( ptr and p )
printf("Hello world! %d \n",ptr[1][3]); // show 4
I'm working on updating a code of a server project since days.
I found a line that I cannot understand (which was commented)
First, I get :
int *t;
Then I got this (commented):
t[*t];
What's the type of this "t[*t]"
The type is an int lvalue. We have two parts:
*t // this is an int
t[ some int ] // this is standard array indexing
Or for a simple example:
int array[] = {1, 2, 3, 4};
int* t = array;
With that setup:
t[*t] == t[1] == 2
Or:
t[*t] = 7;
// now array[] holds {1, 7, 3, 4}
The type is int
*t is equivalent to t[0] as such your expression is equivalent to the follow:
t[*t] == t[t[0]] == t[offset] (if you consider offset = t[0])
By definition of the language, given that t is a pointer, the expression t[*t] is completely equivalent to the expression *(t + *t).
To analyze the type of that expression, let's look at it step for step, from the inside out. I'll replace each expression whole type was identified with «type».
Since t is of type int*, we have *(«int*» + *«int*»).
Dereferencing an int* gives an lvalue of type int. Therefore we get *(«int*» + «int»).
Now adding an integer to a pointer gives, again, a pointer of the same type, so the expression reduces to *«int*».
But that is, again, just the dereferencing of a pointer to int, and therefore the final type of the expression is lvalue int.
Sometimes code is estimated by the number of typed symbols. So I would write a more confusing code but with more characters like:)
( t + *t )[*t];
Relative to your example
*t is some integer stored in t that is *tis equivalent to t[0]. Thus in expression t[*t] there is used the pointer arithmetic
t + *t
or
t + t[0]
that gives some new pointer that then is dereferenced
*( t + *t )
The operator[] of int* always returns an int.
Since *t simply returns the first element of t, t[*t] is the element of tpointed to by the first element of t.
Example:
int *t;
t=new int[5];
for(int i=0;i<5;++i){
t[i]=i+1;
} // t now points to {1,2,3,4,5}
t[*t]; // <--- What does this evaluate to?
In this case t[*t] will be 2.
Because *t is 1, t[1] is the second element in the array, which is 2.
I came across this question:
In the declaration below , p is a pointer to an array of 5 int
pointers.
int *(*p)[5];
which of the following statements can be used to allocate memory for
the first dimension in order to make p an array of 3 arrays of 5
pointers to type int ?
A. p = new int [3][5]*;
B. p = new int (*)[3][5];
C. p = new int [3]*[5];
D. p = new int *[3][5];
E. p = new int (* [3] ) [5];
What is the answer ?
I am not sure I understand the question. Normally I would create a pointer to an array of 5 int as such int* p[5]; I am curious as to why they did it as int *(*p)[5];
Also what does the question want ? Is it asking to initialize (allocate memory) to the first 3 int pointers ? I would appreciate it if someone could explain this to me
F:
using IPA5 = int*[5];
IPA5 * p = new IPA5[3];
Each element p[0], p[1], p[2] is just a plain, typed array of int*. There's nothing dynamic going on beyond the initial dynamic allocation, where 3 is allowed to be a dynamic quantity.
Then p[0][i] for i in [0, 5) is an int *, which you can use in whatever way you like (which includes making it point to the first element of yet anohter dynamic array).
What you would write as:
int* p[5];
is a five element array of pointers to int.
What this declares:
int *(*p)[5];
is a pointer to a five element array of pointers to int, i.e. a pointer to the type of thing you just wrote.
In other words; you could do:
int * a[5];
int * (*p)[5] = &a;
You can mentally read this incrementally as follows:
(*p) // p is a pointer
(*p)[5] // p is a pointer to an array of size 5
int * (*p)[5] // p is a pointer to an array of size 5 of type pointer to int
You need the parentheses around *p, because otherwise:
int ** p[5];
would declare a 5 element array of type int **, or pointer to pointer to int, which is a different thing entirely.
The question is basically asking you to dynamically allocate memory equivalent to three of what a is above, so answer "D" is the correct one.
The answer is
D. p = new int *[3][5];
all the others are syntactically wrong
to realize the difference between
int * p [5];
int * (*p) [5];
consider this example
int *(*p)[5];
int pp[5];
pp[0][0] = new int [5]; //LHS is int , RHS is int ,, compilation error
p[0][0] = new int [5]; //this works because p[0][0] is a pointer not an int
try thinking about each dimension as adding you additional *
back to the question
int *(*p)[5] is giving you 3 * (***p)
so you can assign
p = int *[3][5]
because it has 3 * as well
int* p[5] has type array of size 5 of int*. It decays to int**, so p + 1 will point to the second element of that array.
int *(*p)[5] has type pointer to array of size 5 of int*. You can think of it as decayed two-dimensional array int* [][5]. So p + 1 will point to the second element of the first dimension of that array, that is to the next byte after 5 pointers to int.
Which leads us to the conclusion that the right answer is D.
(This is not to mention that other answers just don't compile regardless of type of p)
What is the answer ?
D
Normally I would create a pointer to an array of 5 int as such int* p[5]; I am curious as to why they did it as int *(*p)[5];
It is not "normally" because int* p[5] is not a pointer to an array of 5 int, it is an array of 5 pointers to int.
Also what does the question want ? Is it asking to initialize (allocate memory) to the first 3 int pointers ?
It's not clear. There is no way "to make p an array of 3 arrays of 5 pointers to type int", to begin with.
I have created a 2D array, and tried to print certain values as shown below:
int a[2][2] = { {1, 2},
{3, 4}};
printf("%d %d\n", *(a+1)[0], ((int *)a+1)[0]);
The output is:
3 2
I understand why 3 is the first output (a+1 points to the second row, and we print its 0th element.
My question is regarding the second output, i.e., 2. My guess is that due to typecasting a as int *, the 2D array is treated like a 1D array, and thus a+1 acts as pointer to the 2nd element, and so we get the output as 2.
Are my assumptions correct or is there some other logic behind this?
Also, originally what is the type of a when treated as pointer int (*)[2] or int **?
When you wrote expression
(int *)a
then logically the original array can be considered as a one-dimensional array the following way
int a[4] = { 1, 2, 3, 4 };
So expression a points to the first element equal to 1 of this imaginary array. Expression ( a + 1 ) points to the second element of the imaginary array equal to 2 and expression ( a + 1 )[0] returns reference to this element that is you get 2.
Are my assumptions correct or is there some other logic behind this?
Yes.
*(a+1)[0] is equivalent to a[1][0].
((int *)a+1)[0] is equivalent to a[0][1].
Explanation:
a decays to pointer to first element of 2D array, i.e to the first row. *a dereferences that row which is an array of 2 int. Therefore *a can be treated as an array name of first row which further decay to pointer to its first element, i.e 1. *a + 1 will give the pointer to second element. Dereferencing *a + 1 will give 1. So:
((int *)a+1)[0] == *( ((int *)a+1 )+ 0)
== *( ((int *)a + 0) + 1)
== a[0][1]
Note that a, *a, &a, &a[0] and &a[0][0] all have the same address value although they are of different types. After decay, a is of type int (*)[2]. Casting it to int * just makes the address value to type int * and the arithmetic (int *)a+1 gives the address of second element.
Also, originally what is the type of a when treated as pointer (int (*)[2] or int **?
It becomes of type pointer to array of 2 int, i.e int (*)[2]
A 2D-array is essentially a single-dimensional array with some additional compiler's knowledge.
When you cast a to int*, you remove this knowledge, and it's treated like a normal single-dimensional array (which in your case looks in memory like 1 2 3 4).
The key thing to recognize here is that the a there holds the value of the address where the first row is located at. Since the whole array starts from the same location as that, the whole array also has the same address value; same for the very first element.
In C terms:
&a == &a[0];
&a == &a[0][0];
&a[0] == &a[0][0];
// all of these hold true, evaluate into 1
// cast them if you want, looks ugly, but whatever...
&a == (int (*)[2][2]) &a[0];
&a == (int (*)[2][2]) &a[0][0];
&a[0] == (int (*)[2]) &a[0][0];
For this reason, when you cast the a to int *, it simply becomes 1-to-1 equivalent to &a[0][0] both by the means of type and the value. If you were to apply those operations to &a[0][0]:
(&a[0][0] + 1)[0];
(a[0] + 1)[0];
*(a[0] + 1);
a[0][1];
As for the type of a when treated as a pointer, although I am not certain, should be int (*)[2].
I'm trying something very simple, well supposed to be simple but it somehow is messing with me...
I am trying to understand the effect of ++ on arrays when treated as pointers and pointers when treated as arrays.
So,
int main()
{
int a[4] = { 1, 4, 7, 9 };
*a = 3;
*(a+1) = 4;
*++a = 4; //compiler error
}
1: So at *(a+1)=4 we set a[1]=4; //Happy
But when *++a = 4;, I'd expect pointer a to be incremented one since ++ is precedent to * and then * kicks in and we make it equal to 4. But this code just does not work... Why is that?
Another problem:
int main()
{
int* p = (int *)malloc(8);
*p = 5;
printf("%d", p[0]);
*++p = 9; //now this works!
printf("%d", p[1]); //garbage
printf("%d", p[0]); //prints 9
}
2: Now *++p = 9; works fine but it's not really behaving like an array. How are two different? This is just incrementing p, and making it equal to 9. If I print p[0], it now prints 9 and I see that though can't access it via p[0] anymore, *(p-1) shows 5 is still there. So indexing a pointer with [0], where exactly does it point to? What has changed?
Thanks a lot all experts!
The array names is not modifiable lvalue so operation ++ is not applied hence ++a that try to modify a is compilation time error (where a is array name).
Note *(a + 1) and *a++ are not same, a + 1 is a valid instruction as it just add 1 but doesn't modify a itself, Whereas ++a (that is equvilent to a = a + 1) try to modify a hence error.
Note 'array names' are not pointer. Pointers are variable but array names are not. Of-course when you assign array name to a pointer then in most expressions array names decays into address of first element. e.g.
int *p = a;
Note p points to first element of array (a[0]).
Read some exceptions where array name not decaying into a pointer to first element?
An expression a[i] is equivalent to *(a + i), where a can be either a pointer or an array name. Hence in your second example p[i] is valid expression.
Additionally, *++p is valid because because p is a pointer (a variable) in second code example.
int a[4] = { 1, 4, 7, 9 };
int *pa=a;
There is one difference between an array name and a pointer that must be kept in mind. A pointer is a variable, sopa=a and pa++ are legal. But an array name is not a
variable; constructions like a=pa and a++ are illegal
int* p = (int *)malloc(8);
Don't cast result of malloc()
Use index with pointer
p[1]=9; // p[1]==*(p+1)