Hi I am learning C++ Primer and have a simple question. Please help me out.
So I know that "int *p = (*q)[10]" where p is a pointer to an array of 10. The question is, in a function definition: "void print(int (*q)[10])" where this pointer is a parameter. how could I get the copy of that pointer. Will that be "int *p = q"?
I technically don't know how to test my correctness in C++.
Thanks
int (*q)[10]
declares q as a pointer to array of 10 ints. Only arrays decay to pointers to their underlying type, but pointers to arrays do not decay to pointers to underlying type, so trying int* p = q; will result in a compilation error. What you need is
int (*p)[10] = q; // copies the pointer q to p
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.
This question already has answers here:
Address of array VS pointer-to-pointer : Not the same?
(2 answers)
Closed 6 years ago.
Consider the below code snippet:
int x[] ={10,20,30,40,50};
int *p;
int **q;
p = x; /* Obviously p now holds base address of array. So no problem here */
q = &x; /* Error. Why? */
I am getting this error in gcc compiler.
error: cannot convert ‘int (*)[5]’ to ‘int**’ in assignment q = &x;
An array variable can be considered as constant pointer to first element of the array. Then why cant I assign the address of the constant pointer i.e) &x to pointer of pointer variable q ?
An array decays to a pointer in certain contexts, like assignment, or passing it to a function.
The address-of operator, &, does not decay the array into a pointer. It's as simple as that. Instead, you get a pointer to the array. In this case:
int (*q)[5];
q= &x; // Works just fine
I am learning c pointer and I follow c4learn as tutorial. In pointer to array of string section, which has following code:
char *arr[4] = {"C","C++","Java","VBA"};
char *(*ptr)[4] = &arr;
I didn't get what is
*(*ptr)[4]
? Wasn't it possible to use it like
**ptr
instead?
Update1:
Currently I am in the next section, function pointer and I saw again similar code:
void *(*ptr)();
char *(*ptr)[4]
is a pointer to a length 4 array of pointers to char (char*). Since arr is a length 4 array of char*, ptr can be made to point to arr by assigning it the address of arr, &arr.
void *(*ptr)();
Is a pointer to a parameterless function returning void*. For example
void* fun(); // function
void *(*ptr)(); // function pointer
p = fun; // function pointer points to function
C syntax can be quite confusing, so it may be easier to illustrate this with some examples. Note that whitespaces between T and ; make no difference.
T name[N]; // size N array of T
T * name[N]; // size N array of pointer to T
T (*name)[N]; // pointer to size N array of T
T ** name[N]; // size N array of pointer to pointer to T
T *(*name)[N]; // pointer to size N array of pointer to T
char *ar[4];
Declares ar as an array of four pointers to chars.
To declare a pointer, you take the declaration of something it can point to, and replace the variable name with (*some_other_name).
So char *(*ptr)[4]; declares ptr as a pointer to an array of four pointers to chars. Normally you can drop the brackets, but in this case, char **ptr[4]; would declare ptr as an array of four pointers to pointers to chars which is not what we want.
Similarly for a function pointer. void *fn() declares a function. void *(*ptr)() declares a pointer that could point to fn. void **ptr() would declare a function with a different return type.
Wasn't it possible to use it like **ptr instead?
Yes, assuming you mean like ptr2 below:
const char* arr[4] = {"C","C++","Java","VBA"};
const char* (*ptr)[4] = &arr;
const char** ptr2 = arr;
There is a difference though... with ptr the type still encodes the array length, so you can pass ptr but not ptr2 to functions like the one below:
template <size_t N>
void f(const char* (&arr)[N]) { ...can use N in implementation... }
Currently I am in the next section, function pointer and I saw again similar code: void *(*ptr)();
That creates a pointer to a function - taking no arguments - returning a void* (i.e. the address of an unspecified type of data, or nullptr).
char *(*ptr)[4] is an array pointer to an array of pointers.
With less obfuscated syntax: if you have a plain array int arr[4]; then you can have an array pointer to such an array by declaring int (*arr_ptr)[4].
So there are arrays, regular pointers and array pointers. Things get confusing because when you use the array name by itself, arr, it decays into a regular pointer to the first element. Similarly, if you have a regular pointer and let it point at the array, ptr = arr; it actually just points at the first element of the array.
Array pointers on the other hand, points at the "whole array". If you take sizeof(*arr_ptr) from the example above, you would get 4*sizeof(int), 4*4=16 bytes on a 32-bit machine.
It should be noted that an array pointer a mildly useful thing to have. If you are a beginner, you don't really need to waste your time trying to understand what this is. Array pointers are mainly there for language consistency reasons. The only real practical use for array pointers is pointer arithmetic on arrays-of-arrays, and dynamic allocation of multi-dimensional arrays.
what means the two stars in this c++ code, I try to convert it in objective c but I never saw that how can I do that?
int **gFFTBitTable = NULL;
Thanks for advance
In both Objective C and C++ it is valid. It is pointer to pointer. As, pointer can keep address of other variable, pointer to pointer can keep address of pointer.
Example,
int i;
int *p = &i; //p is pointer
int **q = &p; //q is pointer to pointer
It means it's a pointer of pointers. If a pointer can be used like an array to keep track of say 10 integers (a row) a pointer of pointers could keep track of say 10 of those pointers (a table)
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.