Is pointer a variable or an address?
Because int** array= new int*[4] is so confusing.
For int** array in this code, the pointer becomes variables to store the pointer addresses, and new int*[4] becomes addresses that will be stored in another pointer.
What am I understanding wrong?
Pointer is a data type, similar to int or char. The data here is a memory address. Pointers are qualified with the types of values expected to be located in the memory at the referred addresses. As other data types, pointers could be used as types for variables, function arguments, array elements etc.
So, int **array is a variable of type int ** which means a pointer to a value of type int * located somewhere in the memory. In turn, int * means a pointer to a value of type int located somewhere in the memory. Or, in short, int ** is a pointer to a pointer to an int.
Expression new int*[4] means allocate in the memory an object of type int *[4] and return a pointer to it. Type int *[4] means an array of four elements of type int * where int *, as we already know, means a point to int value.
So, in the initialization, the types of the left part (int **) and of the right part (int *[]) are different. However, C++ is able to automatically convert arrays into pointers in case the type of array element is the same as the type of the value referred by the pointer. In our case, array element type is int * and the same is the type referred by the pointer. When an array is converted to a pointer, the resulting pointer will refer to the first element of the array.
In this declaration
int** array= new int*[4];
array is a variable that is initialized by the address of the first element of a dynamically allocated array with the element type int *.
If you have an array declared like
T array[N];
where T is some type then a pointer to the first element of the array can be declared like
T *p = array;
If to take into account your array then just T is equal to int *.
Simply put, a pointer is a variable that can store the address of another variable instead of an int or a float or some other value like a "normal" variable.
Like any other variable, the pointer itself also has an address so you can have a pointer to pointer, i.e. a pointer that stores the address of another pointer.
Related
Could somebody explain the difference between these two function declarations below please? As far I know, aDecay() takes a pointer as an argument and if you have an integer int a[5] you can call aDecay(a) or aDecay(&a[0] because an array decays to a pointer.
Now if I want to call pDecay() I have to use pDecay(&a).
How does pDecay force you to use the &.
void aDecay(int *p)
void pDecay(int (*p)[7])
With plain a (or its equal &a[0]) you have a pointer to a single element in the array. A single element is of type int, so a pointer to it must be int*.
If you have a pointer to the actual array, like you get with &a, you no longer have a pointer to a single int element but to the whole array. The type of the array is int[5], and a pointer to it is int(*)[5].
Also note that in neither case you pass the array by value. You pass a pointer by value.
This is not a pointer to function syntax, it's a pointer to array syntax.
In the first example p is a pointer to an array of integers. p[i] is a single int. It cannot be indexed any further.
In the second example p is a pointer to an array of seven integer arrays. p[i] is an array which can be indexed further, i.e. p[i][0] is valid.
Here is an example of using the second approach:
void fill_data(int (*p)[7], size_t n) {
for (size_t i = 0 ; i != n ; i++) {
for (size_t j = 0 ; j != 7 ; j++) {
p[i][j] = (int)(7*i+j);
}
}
}
int main() {
int data[10][7];
fill_data(data, 10);
}
Demo
aDecay takes a pointer to an int.
An array of int can decay to a pointer to the array's first element.
pDecay takes a pointer to an array of seven ints.
An array does not implicitly convert into a pointer to itself.
Passing p will convert the array p to a pointer instead of keeping it as an array (this is called array decay, because the array decays to a pointer).
Passing &p will not convert p to a pointer, because it will convert the pointer to p to a generic pointer, which is not a big deal because it is actually a pointer.
Why we don't want to convert p to a pointer is because arrays are not just pointers. If you think that arrays are just pointers, try to compare sizeof(myArray) with sizeof(myPointer). An array embeds also its size, not only the pointer to the first element.
First of all, you have a misconception in the question: if a is an array, a is always a pointer to that array, i.e. you do pDecay(a) - NOT pDecay(&a). Now, [ ] is a dereferencing operation, so if you say a[5] - you dereference a pointer to a + 5 * bytes in memory occupied by the array's unit. Accordingly, a and &a[0] is exactly the same. a[5] and &(a + 5) is the same.
Answering your question, aDecay(int *p) takes a pointer to integer - nothing asks for an array here. int (*p)[7] is an array of 7 integers and compiler will check that's the case.
How does pDecay force you to use the &.
Because an array doesn't decay to just any pointer. It specifically decays to pointer to first element. The type of pointer to first element of an array of int (i.e. int[n]) is: pointer to int (i.e. int*).
The argument of pDecay is int (*p)[7] which is a pointer to an array of 7 int. An int* is not implicitly convertible to (int (*p)[7]; they are separate, incompatible types. Note that pDecay(&a) won't work either because the type of &a is (int (*p)[5] which is also a different type than (int (*p)[7].
pDecay doesn't force you to use & in general. You could pass an array of arrays, which would then decay to a pointer to first array, which is what pDecay accepts:
int arr[n][7];
pDecay(arr);
Could somebody explain the difference between these two function declarations below please?
int* is a pointer to an int object. int (*p)[7] is a pointer to an int[7] object i.e. an array of 7 int.
I have a struct that looks like this.
struct puzzle {
int d[16];
};
I heard that arrays and pointers are the same in C/C++, so I thought that the struct would store a pointer, and the pointer points to an int array. However, I did simple experiments using a debugger to see how exactly is it stored, and I found out that the array is directly stored in the struct.
Why isn't the array pointer stored in the struct?
Where is the pointer stored at?
I heard that arrays and pointers are the same in C/C++
No! They're very different. An array expression decays into a pointer in many instances, but that's about it. Beyond that arrays and pointers are very different creatures. Understand more about the decaying nature of arrays to avoid confusions like this: What is array decaying?
Why isn't the array pointer stored in the struct? Where is the pointer stored at?
The array is the member of the struct and it's stored as expected. The decayed pointer is obtained implicitly, there's nothing to store here.
struct puzzle s;
int *p = s.d; /* p is now pointing to s.d[0] */
Here s.d gets implicitly converted to int*. Where this decay happens and where it doesn't depends on the language in question. In C++ there're more instances than in C. This is another reason why not to tag a question both C and C++.
I heard that arrays and pointers are the same in C/C++!!!!!
Arrays
An array is a fixed-length collection of objects, which are stored sequentially in memory.
Pointers
A pointer is a value that refers to another object (or function). You might say it contains the object's address.
Arrays decay to pointer (implicit pointer conversion ) when they are passed to functions.
Why isn't the array pointer stored in the struct?
Just because the postman know the address of your house, will you let him stay with you?? Only the members of your family can stay, right? Same in your case, the array is the member of struct.
Arrays and pointers are different things in C.
In many cases array variables can be treated as pointers, e.g. when passed as arguments to a function taking a pointer:
void f(int *p);
main() {
int a[3] = {1, 2, 3};
f(a);
}
But arrays themselves are not pointers at all, they are continuous pieces of memory allocated somewhere (in your case inside a struct).
Arrays and pointers are different types. An array is a named or unnamed extent of memory allocated for its elements.
A pointer is an object that stores an address.
For example if you execute this statement
std::cout << sizeof( puzzle ) << std::endl;
for a structure declared like this
struct puzzle {
int d[16];
};
then the output will be at least not less than the value 16 * sizeof( int ).
If you will execute the same statement
std::cout << sizeof( puzzle ) << std::endl;
for a dtructure declared like this
struct puzzle {
int *d;
};
then the output will be at least equal to the value sizeof( int * ).
Arrays are implicitly converted to pointers to their first elements when they are used in expressions.
For example
int a[16];
int *p = a;
Here in the second declaration array a used as initializer is converted to pointer to its first element.
There is no difference between using an array or a pointer with the subscript operator like
a[i]
or
p[i]
because in the both cases this expression is evaluated like
*( a + i )
or
*( p + i )
that is again the array is converted to pointer to its first element and there is used the pointer arithmetic in the expression.
Arrays have sequential access.a[0] location is =100 means ,a[1] would be in 101, a[2] in 102.
Pointers are not sequential they are randomly stored based on the address.
int (*arr)[5] means arr is a pointer-to-an-array of 5 integers. Now what exactly is this pointer?
Is it the same if I declare int arr[5] where arr is the pointer to the first element?
Is arr from both the examples are the same? If not, then what exactly is a pointer-to-an-array?
Theory
First off some theory (you can skip to the "Answers" section but I suggest you to read this as well):
int arr[5]
this is an array and "arr" is not the pointer to the first element of the array. Under specific circumstances (i.e. passing them as lvalues to a function) they decay into pointers: you lose the ability of calling sizeof on them.
Under normal circumstances an array is an array and a pointer is a pointer and they're two totally different things.
When dealing with a decayed pointer and the pointer to the array you wrote, they behave exactly the same but there's a caveat: an array of type T can decay into a pointer of type T, but only once (or one level-deep). The newly created decayed type cannot further decay into anything else.
This means that a bidimensional array like
int array1[2][2] = {{0, 1}, {2, 3}};
can't be passed to
void function1(int **a);
because it would imply a two-levels decaying and that's not allowed (you lose how elements of the array are laid out). The followings would instead work:
void function1(int a[][2]);
void function1(int a[2][2]);
In the case of a 1-dimensional array passed as lvalue to a function you can have it decayed into a simple pointer and in that case you can use it as you would with any other pointer.
Answers
Answering your questions:
int (*arr)[5]
this is a pointer to an array and you can think of the "being an array of 5 integers" as being its type, i.e. you can't use it to point to an array of 3 integers.
int arr[5]
this is an array and will always behave as an array except when you pass it as an lvalue
int* ptrToArr = arr;
in that case the array decays (with all the exceptions above I cited) and you get a pointer and you can use it as you want.
And: no, they're not equal otherwise something like this would be allowed
int (*arr)[5]
int* ptrToArr = arr; // NOT ALLOWED
Error cannot convert ‘int (*)[5]’ to ‘int*’ in initialization
they're both pointers but the difference is in their type.
At runtime, a pointer is a "just a pointer" regardless of what it points to, the difference is a semantic one; pointer-to-array conveys a different meaning (to the compiler) compared with pointer-to-element
When dealing with a pointer-to-array, you are pointing to an array of a specified size - and the compiler will ensure that you can only point-to an array of that size.
i.e. this code will compile
int theArray[5];
int (*ptrToArray)[5];
ptrToArray = &theArray; // OK
but this will break:
int anotherArray[10];
int (*ptrToArray)[5];
ptrToArray = &anotherArray; // ERROR!
When dealing with a pointer-to-element, you may point to any object in memory with a matching type. (It doesn't necessarily even need to be in an array; the compiler will not make any assumptions or restrict you in any way)
i.e.
int theArray[5];
int* ptrToElement = &theArray[0]; // OK - Pointer-to element 0
and..
int anotherArray[10];
int* ptrToElement = &anotherArray[0]; // Also OK!
In summary, the data type int* does not imply any knowledge of an array, however the data type int (*)[5] implies an array, which must contain exactly 5 elements.
A pointer to an array is a pointer to an array of a certain type. The type includes the type of the elements, as well as the size. You cannot assign an array of a different type to it:
int (*arr)[5];
int a[5];
arr = &a; // OK
int b[42];
arr = &b; // ERROR: b is not of type int[5].
A pointer to the first element of an array can point to the beginning of any array with the right type of element (in fact, it can point to any element in the array):
int* arr;
int a[5];
arr = &a[0]; // OK
int b[42];
arr = &b[0]; // OK
arr = &b[9]; // OK
Note that in C and C++, arrays decay to pointers to the type of their elements in certain contexts. This is why it is possible to do this:
int* arr;
int a[5];
arr = a; // OK, a decays to int*, points to &a[0]
Here, the type of arr (int*) is not the same as that of a (int[5]), but a decays to an int* pointing to its first element, making the assignment legal.
Pointer to array and pointer to first element of array both are different. In case of int (*arr)[5], arr is pointer to chunk of memory of 5 int. Dereferencing arr will give the entire row. In case of int arr[5], arr decays to pointer to first element. Dereferencing arr will give the first element.
In both cases starting address is same but both the pointers are of different type.
Is it the same if i declare int arr[5] where arr is the pointer to the first element? is arr from both example are same? if not, then what exactly is a pointer to an array?
No. To understand this see the diagram for the function1:
void f(void) {
int matrix[4][2] = { {0,1}, {2,3}, {4,5}, {6,7} };
char s[] = "abc";
int i = 123;
int *p1 = &matrix[0][0];
int (*p2)[2] = &matrix[0];
int (*p3)[4][2] = &matrix;
/* code goes here */
}
All three pointers certainly allow you to locate the 0 in matrix[0][0], and if you convert these pointers to ‘byte addresses’ and print them out with a %p directive in printf(), all three are quite likely to produce the same output (on a typical modern computer). But the int * pointer, p1, points only to a single int, as circled in black. The red pointer, p2, whose type is int (*)[2], points to two ints, and the blue pointer -- the one that points to the entire matrix -- really does point to the entire matrix.
These differences affect the results of both pointer arithmetic and the unary * (indirection) operator. Since p1 points to a single int, p1 + 1 moves forward by a single int. The black circle1 is only as big as one int, and *(p1 + 1) is just the next int, whose value is 1. Likewise, sizeof *p1 is just sizeof(int) (probably 4).
Since p2 points to an entire ‘array 2 of int’, however, p2 + 1 will move forward by one such array. The result would be a pointer pointing to a red circle going around the {2,3} pair. Since the result of an indirection operator is an object, *(p2 + 1) is that entire array object, which may fall under The Rule. If it does fall under The Rule, the object will become instead a pointer to its first element, i.e., the int currently holding 2. If it does not fall under The Rule -- for instance, in sizeof *(p2 + 1), which puts the object in object context -- it will remain the entire array object. This means that sizeof *(p2 + 1) (and sizeof *p2 as well, of course) is sizeof(int[2]) (probably 8).
1 Above content has been taken from More Words about Arrays and Pointers.
The address of the whole array, and the address of the first element, are defined to be the same, since arrays in C++ (and C) have no intrinsic padding besides that of the constituent objects.
However, the types of these pointers are different. Until you perform some kind of typecast, comparing an int * to an int (*)[5] is apples to oranges.
If you declare arr[5], then arr is not a pointer to the first element. It is the array object. You can observe this as sizeof( arr ) will be equal to 5 * sizeof (int). An array object implicitly converts to a pointer to its first element.
A pointer to an array does not implicitly convert to anything, which may be the other cause of your confusion.
If you write int arr[5], you are creating an array of five int on the stack. This takes up size equal to the size of five ints.
If you write int (*arr)[5], you are creating a pointer to an array of five int on the stack. This takes up size equal to the size of a pointer.
If it is not clear from the above, the pointer has separate storage from the array, and can point at anything, but the array name cannot be assigned to point at something else.
See my answer here for more details.
If I have the following pointer variable declarations:
int *a;
int **c;
Regarding to the type and what values each will hold, will it be as follows:
a is of type int*, and will hold a memory address
*a is of type int, and will hold the value of the variable the pointer is pointing to
c is of type int**, and will hold ?????????????????????
c* is of type int*, and will hold the memory address of the pointer it is pointing at
c** is of type int, and assuming that pointer c is pointing to pointer b, and pointer b is pointing to variable a, here, the value held will be the value of the variable a
Is it correct this way, except c which I'm not sure about?
Thanks.
int *a;
int **c;
You are correct about a. It is more common to say a holds a pointer to int.
c is of type int** and will hold a pointer to a pointer to int.
*c is of type int*, and will hold a pointer to int.
**c is of type int, and will hold an integer value. You are correct about c pointing to b and b pointing to a.
See cdecl for some help. :)
c is of type int**, and will hold ?????????????????????
'c' also holds a memory address, just as 'a' does. The difference is that 'c', when dereferenced, will return another memory address. You're just adding another level of indirection.
In your example, c will hold a pointer to an int*; that is, c is a pointer to a pointer. It can be used for multidimensional arrays (like matrices) and it can be used as a function parameter to change a user's int*.
-- a is of type int*, and will hold a memory address
Correct
-- *a is of type int, and will hold the value of the variable the pointer is pointing to
Not exactly: *a will be a reference to the variable the adress points to. You see this when trying *a = 8; and int * x = &(*a)).
If it was a value you couldn't change it. But since it is a reference the value is "routed" to the original place...in this case the memory a points to.
-- c is of type int**, and will hold ?????????????????????
c holds a memory address pointing to a memory address pointing to an int.
*c holds a reference to a memory adress pointing to an int. So you can do: *c = a;
**c is the same as *a.
Every pointer holds memory address. In this case, c is a pointer to int* so, it will hold a memory address of such a variable.
Often, double pointers are used to create dynamic multiarrays in C. You can see it here
C is of type int*. As evident from that, it will hold a data of type int* which in itself is a memory address.
This concept is called far pointer and there can be multiple far pointers up to a certain limit.
Like int** c, you can also have int*** d point to int** c. This is like a queue with every pointer pointing to the next pointer and the front having the data as the actual variable.
The simplest thing that I can think of is playing with spaces. The compiler does not really care, but it makes reasoning easier due to the fact that the syntax of declarations and the usage are the same (by design):
Given:
int ***a; // declaration
int*** a; // type of a is an int*** (read: pointer to pointer to pointer to int)
int** *a; // the type of the object pointed by a (*a) is int**
int* **a; // the type of **a is int*
int ***a; // the type of ***a is int
Disclaimer: this is with respect to data types. Whether you can or not dereference a pointer at runtime is a different issue (has it been initialized, does it point to valid memory...?)
I don't understand what the datatype of this is. If its a pointer or an array. Please explain in simple terms. To quote what was in the book-
If you want to pass an array of pointers into a function, you can use the same method that you use to pass other arrays—simply call the function with the array name without any indexes. For example, a function that can receive array x looks like this:
void display_array(int *q[])
{
int t;
for(t=0; t<10; t++)
printf("%d ", *q[t]);
}
Remember, q is not a pointer to integers, but rather a pointer to an array of pointers to
integers. Therefore you need to declare the parameter q as an array of integer pointers,
as just shown. You cannot declare q simply as an integer pointer because that is not
what it is.
cite: C++: The Complete Reference, 4th Edition by Herbert Schildt, Page 122-123
This is how it's built up:
int is the type "int".
int* is the type "pointer to int"
int* [] is the type "array (of unknown bound/length) of pointer to int"
int* p[] is the declaration of a variable or parameter named p of the type above.
... pointer to an array of pointers to integers
No it's not. q is the type int *[]. Which is an invalid (or possibly incomplete, depending on context) type in C++, and only valid in some places in C. Arrays must have a size.
The type int *[] is an (unsized) array of pointers to int. It is itself not a pointer.
The confusion probably comes from the fact that an array can decay to a pointer to its first element.
For example, lets say we have this array:
int a[20];
When plain a is used, it decays to a pointer to its first element: a is equal to &a[0].
int *p[]
// ^
p is
int *p[]
// ^^
p is an array of unspecified size (possibly illegal, depends on context)
int *p[]
// ^^^^^
p is an array of unspecified size of pointers to int
Meaning each element of p is a pointer:
int foobar = 42;
p[0] = NULL;
p[1] = &foobar;
I don't understand what the datatype of this is
If it's any comfort, neither does the author of the book you are reading.
Remember, q is not a pointer to integers, but rather a pointer to an array of pointers to integers.
This is bullschildt.
Before adjustment of parameters, q is an array of pointers to integers.
After adjustment of parameters, q is a pointer to the first element of an array of pointers to integers. Equivalent to int** q, a pointer to pointer to an int.
Nowhere is it "a pointer to an array of pointers to integers". That would have been int* (*q)[].
I would advise to stop reading that book.
The key here is that any array that is part of a parameter list of a function, gets adjusted ("decays") into a pointer to the first element. So it doesn't matter if you type int* q[666] or int* q[], either will be silently replaced by the compiler with int** "behind the lines".
This is actually the reason why we can write [] in a parameter list - normally an empty array would be an incomplete type that can't be used before completion elsewhere. But since parameters always get adjusted, they are never of array type, and it doesn't matter that the original type was incomplete.