Why is address considered a pointer? [duplicate] - c++

This question already has answers here:
C: differences between char pointer and array [duplicate]
(14 answers)
C++ - Is an array a pointer? [duplicate]
(2 answers)
Closed 7 years ago.
char list[] = "World";
char *ptr = list + 2;
char **p = &ptr;
The question: Why is &ptr of type char**? I understand that p points to a pointer to an array but isn't the address of ptr a char*?
I have looked at Is an array name a pointer?, is it possible that the array is considered a pointer as well in this case?

Is array considered a pointer also?
No, pointers and arrays are distinct types. The confusion arises partly because in many cases pointers can decay to arrays, and in functions, array-like parameters are adjusted to pointers.
Why is &ptr of type char**?
Because ptr is of type char*. Applying the address-of operator to an object of a type gives you a pointer to that type.
I understand that p points to a pointer to an array
No, it points to a pointer, which points to an element of an array.
A pointer to an array is a different type altogether. For example, here a real pointer to an array is made to point to an array:
int a[8];
int (*arr)[8] = &a;

You have to follow things step-wise to easily understand this.
char* ptr is a pointer to char because it is pointing to a char.
What is p pointing at?
It is pointing at a char*. Therefore, it is a pointer to a pointer to a char. That is p is of type char**.

&ptr is a char ** simply because ptr is a char*. list is not a pointer, it's an array. But ptr is declared as char *, so it's a pointer.
ptr is initialised from a pointer list + 2. The expression list + 2 uses the operator +, which performs the array-to-pointer conversion on its operands (if applicable). Therefore, when evaluating list + 2, a temporary pointer to char is created from list using the array-to-pointer conversion. Then another temporary pointer is created by adding 2 to the first one, and this second temporary is then used to initialise ptr.

An array's name "decays" into a pointer to its first element under most circumstances.
In this case, the array consists of 2 bytes. Its name list is a char * pointing to the W.
Consequently, list + 2 points to the r. This pointer is stored into ptr, a char * as well.
A char * is a pointer to char. Consequently, a char ** is a pointer to a pointer to char, and that's exactly what &ptr is.

Array is not a pointer. It is an array. However, array can decay to pointer in certain contexts, of which most notable is passing an array to a function.

A pointer is also the first element of an array, so the address of the first element of the array and the pointer of the array would be the same

Related

How the pointer and the pointer's adress can share the same memory adress? [duplicate]

This question already has answers here:
Address of an array
(3 answers)
Closed 4 years ago.
In this code, I have read that ar is equivalent to &ar[0], so we can write int* pointer = ar; while working with pointers .It seems ar is a pointer to ar[0]. So how &ar and ar can be same? Isn't ara pointer to ar[0] and &ar is the memory location of the pointer ar?
int ar[3] = {1,2,3};
cout<<ar<<endl;
cout<<&ar<<endl;
&ar is the address of the array, its type is "pointer to an array of three integers".
ar, when passed to the ostream decays to a pointer to its first element, which is of type "pointer to integer". The same happens when it is assigned to an according pointer.
When printing pointers, other than those to char, unsigned char and signed char, the pointers are converted to "pointer to void".
In summary, printing the array or printing the address of the first element generates the same output, because the address of the array is also the address of the first element. Their types differ, but that is irrelevant because they are converted to void anyway.

c++ pass array by value or pointer to function syntax

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.

Double Pointers and a Parenthesis between them

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.

Advanced Pointer convoluted syntax

I was fidgeting with the pointers thingy.graduated from pointers -> array of pointers -> function pointers -> pointer to pointers..
Here's what i am stuck at...mostly the convoluted syntax.
Lets say i have an array of integers.
int arr[4] = {1,2,3..};
also i have array of pointers
int* ptr[4];
ptr[0] = arr;
here ptr[0] will point to 1
and ptr[1] will point to some other location
This works perfectly !!
Now considering above background i tried this.
char* crr[4] ={"C","C++","C#","F#"};
char** btr[4];
btr[0] = crr;
which works as pointer in oth element of btr is pointing to another pointer element in crr.
Then i tried this.
char* crr[4] ={"C","C++","Java","VBA"};
char** btr[4]= &crr; // Exception: cannot convert char* [4] * to char**[4]
but when i do this it works :O
char* crr[4] ={"C","C++","Java","VBA"};
char* (*btr)[4]= &crr;
i have not understood the last two scenarios. The use of brackets on RHS Pls explain.
char** btr[4]= &crr; // Exception: cannot convert char* [4] * to char**[4]
That's trying to initialise an array (of pointers to pointers) from a pointer, which you can't do. If you wanted to initialise the first element to point to crr (as in your first example), then you'd do
char** btr[4]= {crr};
The last example is declaring a pointer to an array (of pointers), and initialising it from a compatible pointer.
Note that your original array should be of const char *, not char *, since it contains pointers to (constant) string literals.
Except when it is the operand of the sizeof or unary & operators, or is a string literal being used to initialize another array in a declaration, an expression of type "N-element array of T" will be converted ("decay") to an expression of type "pointer to T", and the value of the expression will be the address of the first element of the array.
When you write
btr[0] = crr;
the expression crr has type "4-element array of char *"; since it is not the operand of a sizeof or & operator, it is converted to type "pointer to char *", or char **. This matches the type of btr[0].
However, when you write
char** btr[4]= &crr;
the expression crr is the operand of the & operator; thus, the type of the expression &crr is "pointer to 4-element array of char *", or char *(*)[4].
The parentheses are necessary because the postfix [] operator has higher precedence than the unary * operator; the expression *a[i] will always be parsed as *(a[i]). Thus,
T *a[N]; // a is an N-element array of pointer to T
T (*a)[N]; // a is a pointer to an N-element array of T
T *(*a)[N]; // a is a pointer to an N-element array of pointer to T
The same is true for pointers and functions:
T *f(); // f is a function returning a pointer to T
T (*f)(); // f is a pointer to a function returning T
T *(*f)(); // f is a pointer to a function returning pointer to T
Let's look at your definitions:
Array of size 4 of char*
char* crr[4] ={"C","C++","Java","VBA"};
Array of size 4 of char**
char** btr[4]
Pointer to an array of size 4 of char*
char* (*btr)[4]
Now you are trying to assign Array of size 4 of char* to Array of size 4 of char** and they are of different type, so you, obviously, have a error. Still there is another rule(which is dominated): you can't initialize array without curly braces, so array should be initialized with new data not to be a pointer to other array.
And you have absoulutely legal pointer type Pointer to an array of size 4 of char* to which your array address could be assigned

C++: When using memcpy, what is the difference between myArray and &myArray? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How come an array’s address is equal to its value in C?
In the situation:
int x = 5;
unsigned char myArray[sizeof (int)];
This line...
memcpy (&myArray , &x , sizeof (int));
... is producing identical results to:
memcpy (myArray , &x , sizeof (int));
I am very much a novice to C++, but I was under the impression that arrays are just a pointer to their data. I was shocked when &myArray was working identical to myArray. I would have thought it would be trying to copy to the ADDRESS of the pointer, which would be very bad!
Two things about arrays:
Arrays "decay" to pointers of their element type. This is why the second version is working. See this :Is an array name a pointer?
There is such a thing as a "pointer to array". They are rarely used, but look like this:
int a[5];
int (*b)[5] = &a; // pointer to an array of 5 ints
The & operator when used on an array gives you a pointer to array type, which is why the following doesn't work:
int* b = &a; // error
Since memcpy's parameter is a void*, which accepts any pointer type, both &myArray and myArray work. I'll recommend going with myArray though as it's more idiomatic.
You are correct in believing the types are different. &myArray is a unsigned char(*)[] (a pointer to an array of unsigned char) and myArray (when passed to a function as an argument) becomes type unsigned char* (pointer to unsigned char). However, note that even though the types are different, there value is the same address. The reason both work with memcpy is because memcpy takes void* and doesn't care about the type.
what is the difference between myArray and &myArray?
They both point to the first element of myArray.
The name of an array usually evaluates to the address of the first element of the array, so myArray and &myArray have the same value.
memcpy function takes memory address to destination as input argument. As myArray and &myArray points to the same place, so the effort is the same:
void* memcpy( void* dest, const void* src, std::size_t count );
Parameters
dest - pointer to the memory location to copy to
src - pointer to the memory location to copy from
count - number of bytes to copy