How is const char** x and const char* x[] similar? - c++

I have a hard time understanding or finding a simple explanation of what const char** x is and how to use it?
I kind of understand that char* x[] is an array of char pointers.
One explanation for the char** x I found says that "they are variable pointers to an array of variable pointers to const chars".
I am confused. Is x an array of pointers or just one pointer that points to an array of pointers?

If I wrote T *x, you'd understand that, I assume? x is simply a pointer to an object of type T. And that object may be the first element in an array of T. Whereas T x[10] really is an array of 10 T.
In your case, T is const char *. So x is a pointer to a const char *.

[] it mostly a shortcut for declaring arrays of thing, and not really a type. It is used when declaring the elements of the array, or specifying how many "slots" that array have.
But C don't handle entire arrays as if it was one single thing, so the resultant variable you get from that operation is a char * pointer pointing to the first element of that array, so that char x[] and char *x is somewhat implied of being the same type.
When declaring char x[] = "string";, for instance, x is a variable of type char * that points to the first element of the array, x[0] which value is 's'.
You can reapply the concept to a matrix or an array of arrays, which is the same as a pointer to a collecion of pointers.
So while char *x may be a string, char **x may be a list of strings.

for every type you use * it is a pointer to that type. it might point to one element or to the first element (at the first time you assign it) of a sequence of elements on the memory. with a pointer you can use pointer arithmetik for example x++ to navigate to the next element, you can also use the index operator x[1] on it. pointer arithmetik cannot be applied to a const pointer, witch is obvious since you declared it to be constant.
for every type you use [] it is an array. with an array you cannot use pointer arithmetik, only the the [] operator lets you access the elements of an array.
you can say that a const pointer is similar the an array when it comes to accessing element.
Use array when you know at compile time what size it should have. these will reside on the stack.
Use pointers when you have to allocate memory at runtime or you wich to use pointer arithmetik. memory allocated at runtime resides on the heap.
here a lecture that might help you understand better.
I hope i didn't tell any mistakes, it's been a while since i used C the last time :/

Here's one example:
char ch;
char *pch = &ch;
char **ppch = &pch;
In this case, no array is involved.
There is one variable that holds a character (ch).
Then there is one variable that holds a pointer (pch). This is simply an address of a location in memory that holds data. But the compiler and the programmer are also interested in the type of the value that is stored in that location (for example, to know how many bytes it takes, or which operations are allowed on that value). So the pointer has a type that is related to the type of the value it's pointing to. In this case, pch is pointing to a character value, so the type is char *.
And then there's another variable that holds a pointer (ppch). Again it's just an address of a location in memory, but this time the value that is stored in that location is a pointer. So there are two pointers involved, ppch and the pointer it's pointing to. Both pointers have a type. ppch is a char ** - pointer to a pointer to char. The value it's pointing to is a char * - pointer to a character.
A pointer can point to a single value, but in some cases it's also useful if there is a sequence of values with the same type (an array). In that case, the pointer can point to any of the values in the sequence, and using pointer arithmetic it can be changed to point to other values in the same sequence.
So just like char * is a pointer that can point to a character, it can also point to any value in a sequence of a characters, and in many cases it's useful if it points to the first value in the sequence.
char ** points to a char * value, which again can be a single value or one of many in a sequence of values (and more specifically, the first in the sequence).
This is NOT the same as char *array[] which is the actual sequence of pointers. The difference is important:
char *pointers[5];
char **pp;
Here, char *pointers[5] is an array of 5 pointers. It's the actual sequence. sizeof(pointers) is 5 times the size of a single pointer.
But pp is just a pointer - it's a variable that holds a single pointer, and sizeof(pp) is the size of a single pointer. As it's a pointer to pointer, it can also point to the first element of pointers (or to any other char * value, including other elements of pointers).
Now there's only the question of const. This only affects the type that it appears with (this is a bit confusing, because C allows different orders, and const char is the same as char const). So const char **pp is a non-const pointer (meaning the pointer can change) to a non-const pointer (so that pointer can also change) to a const char (meaning that the value of the character cannot be modified by pp).
So pp itself can be changed by the program - it can point to different pointers. The pointer that it's pointing to can also change - it can point to different characters. But the characters themselves cannot be changed using pp.
For a reasonable example, we need a few const char pointers, and a few characters to point to. The easiest way to get those is to use arrays:
char seq1[5] = { 'a', 'b', 'c', 'd', 'e' };
char seq2[3] = { 'x', 'y', 'z' };
const char *p1;
const char *p2;
const char **pp;
p1 = &seq1[0]; /* valid, same as p1 = seq1 */
p1 = &seq1[3]; /* valid */
*p1 = 's'; /* invalid - the character that p1 points to cannot be changed by p1 */
p2 = seq2; /* valid */
pp = &p1; /* valid */
*pp = &seq1[2]; /* valid - pp is a non-const pointer, so the value it points to can change */
pp = &p2; /* valid - pp itself is non-const */
**pp = 't'; /* invalid - same as *(*pp) which is *p2 which is const when accessed by pp */
Note that the meaning of const is not that the value cannot ever change, but that it cannot be changed by the const variable (or the const pointer). The following example should clarify:
char ch;
char *pch = &ch;
const char *cpch = &ch;
ch = 'a'; /* fine - ch is not const */
*pch = 'b'; /* fine - pch does not point to a const value */
*cpch = 'c'; /* invalid - cpch points to a const value */

Related

How can C++ array pointers have different location, yet point to the same element?

I know the variable that holds the array stores the address of the array and any indexing on it performs a pointer arithmetic on the same. While I was brushing up my basics this is what I found.
int main() {
int equal;
char c[] = {'a', 'b', 'c'};
char* p = c;
char* q = &c[0];
cout<<*p<<endl;
cout<<*q<<endl;
cout<<&p<<endl;
cout<<&q<<endl;
if (c==q) {
equal=1;
}
cout<<equal<<endl;
}
//output
a
a
0x7ffda22e0a60
0x7ffda22e0a68
1
Derefencing p,q is giving me the same value, yet the addresses of p,q are different. How is this possible?
When you allocate an array, that variable you assign the array to points to the beginning of that array. The beginning of that array is an address in the memory.
The address of the beginning of an array is the address of its first element, so it doesn't matter whether you take char *x = arr; or char *y = &arr[0]; they will be the same.
Now x and y are allocated on the stack and are two different variables, so they will oviously have different addresses. Hence
&x == &y // false
When writing T* x you are declaring a pointer to an object of type T. This pointer x is essentially an integral value containing a number that represents an address in the memory.
A pictorial representation of your code: (addresses are imaginary)
p and q are separate variables, they have their own address. However, the address they point to, are the same.

Initializing a char pointer C++ [duplicate]

This question already has answers here:
What is the type of string literals in C and C++?
(4 answers)
Closed 5 years ago.
How is this even possible?
const char *cp = "Hello world";
I am currently reading C++ primer and i found this example (I am a very beginner).
Why is it possible to initialize a char pointer with a string? I really can't understand this example, as far as I know a pointer can only be initialized with & + the address of the object pointed OR dereferenced and THEN assigned some value.
String literals are really arrays of constant characters (with the including terminator).
When you do
const char *cp = "Hello world";
you make cp point to the first character of that array.
A little more explanation: Arrays (not just C-style strings using arrays of char but all arrays) naturally decays to pointers to their first element.
Example
char array[] = "Hello world"; // An array of 12 characters (including terminator)
char *pointer1 = &array[0]; // Makes pointer1 point to the first element of array
char *pointer2 = array; // Makes pointer2 point to the first element of array
Using an array is the same as getting a pointer to its first element, so in fact there is an address-of operator & involved, but it's implied and not used explicitly.
As some of you might have noted, when declaring cp above I used const char * as the type, and in my array-example with pointer1 and pointer2 I used a non-constant plain char * type. The difference is that the array created by the compiler for string literals are constant in C++, they can not be modified. Attempting to do so will lead to undefined behavior. In contrast the array I created in my latter example is not constant, it's modifiable and therefore the pointers to it need not be const.
"Hello world" is a read-only literal with a const char[12] type. Note that the final element is the NUL-terminator \0 which the language exploits as an "end of string" marker. C and C++ allow you to type a literal using " surrounding the alphanumeric characters for convenience and that NUL-terminator is added for you.
You are allowed to assign a const char[12] type to a const char* type by a mechanism called pointer decay.
pointer can only be initialized with & + the address of the object pointed
int i = 0;
int *pointer = &i;
It's correct but it not the only way to initialized pointers. Look at below exmaple.
int *pointer;
pointer = (int*)malloc(100 * sizeof(int));
It is how you initialized pointers by allocating memory to it.
How is this even possible?
It works because "Hello World" is a string constant. You do not need to allocate this memory, it's the compiler's job.
By the way, always use smart pointer instead of raw pointer if you're using c++.

difference between pointer to an array and pointer to the first element of an array

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.

Differences in using array in main program or in functions sub-routines

I'v got some question about using array pointers in program.
When I use some array name (which is a const pointer to first array element)
char charTab[] = "ABCDEFGHIJKLMNOPRSTUWXYZ"; /* Basic data buffer */
char *charPtr = charTab; /* Assign */
charPtr += 3; /* It's ok, now we point 4th element */
charTab += 3; /* No, the lvalue required for '+' operand */
But when I create let's say the following function:
void CharTabMove(char *tabToMove, int noToMove);
With definition
void CharTabMove(char *tabToMove, int noToMove)
{
printf("-------IN FUNCTION---------\n");
printf("It's pointing to %c\n", *tabToMove);
tabToMove += noToMove;
printf("Now it's pointing to %c\n", *tabToMove);
printf("-------LEAVING FUNCTION---------\n");
fflush(stdout);
}
The function is allow to move this pointer along the array with no problem. Sure, after leaving the function the pointer will be still pointing to first element of charTab, but why the function is allowed to move the constant pointer?
Thanks in advice for response, I'm trying to explain that to my 11 yo nephew :)
---EDIT after couple of years ---
Ok, time pass and now I see why my question was not formulated accurately. I misguided you by using term const pointer referring to array name before and after passing it function. To rephrase, question boils down to:
Why this is not allowed:
char charTab[] = "ABCDEFGHIJKLMNOPRSTUWXYZ"; /* Basic data buffer */
charTab += 3; /* No, the lvalue required for '+' operand */
While this is allowed:
char charTab[] = "ABCDEFGHIJKLMNOPRSTUWXYZ"; /* Basic data buffer */
void CharTabMove(char *tabToMove, int noToMove)
{
tabToMove += noToMove;
}
CharTabMove(charTab)
And the answer is as I gathered and refined all of your answers, charTab acts almost like constant pointer to first element of array, but essentially is not an lvalue or a pointer statement, so arthmetic operations are not allowed. When passing it to function, this almost like constant pointer to first array element will be casted and passed by value as regular pointer, so operations can be executed on it.
There is one difference between an array name and a pointer that must be kept in mind. A pointer is a variable, so pa=a and pa++ are legal. But an array name is not a
variable; constructions like a=pa and a++ are illegal. here pa is pointer.
charPtr += 3; ==> this is allowed because this is pointer , pointer arithmetic is allowed and you can change the location of pointer.
charTab += 3; ==> here this is illegal.you should not change the position of array.
and
tabToMove ==> is character pointer.you can modify it.
First of all, the name of the array is not a constant pointer, it is just name of the array; the point is that an array in almost any context decays to a pointer to the first element of the array.
The array by itself cannot be incremented, but, once it decays to a pointer to the first element and is assigned to some pointer variable, it can be incremented (the second step is fundamental, since, to increment something, you must have an lvalue).
Now, functions cannot directly receive arrays as parameters (even if you write an array in the function signature it's implicitly interpreted as a pointer), so, when you pass an array to a function it surely decays to a pointer to its first element, and it's used to initialize the parameter of the function, which then can be incremented as you wish: in facts, the parameter tabToMove is just a local variable of type char * which is initialized with the passed argument, i.e. the pointer to the first element of the array.
In other words, if you write
char foo[]="asdasdas";
CharTabMove(foo, 5);
is like you were doing
char foo[]="asdasdas";
char *tabToMove=foo;
int noToMove=5;
CharTabMove(tabToMove, noToMove);
charTab is an array; charPtr and tabToMove are pointers. If you were able to change charTab you'd effectively lose track of where the beginning of the array is. If you change charPtr or tabToMove you don't have the same problem -- they're copies of the pointer to the beginning of the array.
but why the function is allowed to move the constant pointer?
It's not a constant pointer -- you've declared it as char *.
You cannot change a const pointer.
Actually, in the function, you just change a non-const pointer which just has the same value(passed by value when calling function) of your const point.

Cannot cast array to pointer

I have the following source:
#include <iostream>
using namespace std;
void main(int j)
{
char arr[10][10];
char** ptr;
ptr = arr;
}
when I compile it using VS2010 I get this error:
error : a value of type "char (*)[10]" cannot be assigned to an entity of type "char **"
I thought arrays in c++ were just pointers. So a char[][] could also be char**. What am I doing wrong?
Arrays aren't pointers.
An array decays to a pointer in most circumstances, but this isn't recursive. So a T[] decays to a T *, but a T[][] doesn't decay to a T**.
I suggest reading the whole of the C FAQ chapter on arrays and pointers; in particular, the section on 2D arrays and pointers-to-pointers.
The existing answers, though correct, don't make it very clear that there is a fundamental reason (apart from the language rules) why you cannot cast char [10][10] to char **. Even if you force the cast by saying something like
char arr[2][2];
char ** ptr = (char **)arr;
it won't actually work.
The reason is that in C and C++ a two-dimensional array is laid out in memory as an array of arrays. That is, in C a two-dimensional array is laid out in memory as a single allocation,
arr -> arr[0][0]
arr[0][1]
arr[1][0]
arr[1][1]
You'll notice that arr doesn't point to a char * but to arr[0][0] which is a char; therefore, while arr can be cast to a char *, it cannot be cast to a char **.
The correct forced cast would be
char arr[2][2];
char * ptr = (char *)arr;
If you don't want to force the cast (always a good idea if possible!) you would say
char arr[2][2];
char * ptr = arr[0];
or, to make the outcome clearer,
char arr[2][2];
char * ptr = &arr[0][0];
And you now have (in effect) a pointer to an array of 4 characters. [Proviso: I can't find anything in the C standard that prohibits an implementation from adding padding between two rows of an array, but I don't believe that any real-world implementations do so, and common coding practice depends on the assumption that there will be no such padding.]
If you really needed to convert arr to a char ** you would have to explicitly create an array of pointers:
char arr[2][2]
char * arr_ptrs[2];
char ** ptr;
arr_ptrs[0] = arr[0];
arr_ptrs[1] = arr[1];
ptr = arr_ptrs;
The C language could in principle do this for you automatically if you tried to cast a two-dimensional array to a pointer-to-pointer but that would violate the programmer's expectation that a cast does not have side-effects such as allocating memory.
In Java, by way of comparison, a two-dimensional array is always an array of pointers to arrays, so that the array
char arr[][] = { {'a', 'b'}, {'c', 'd'} };
is laid out in memory as three separate allocations, in arbitrary order and not necessarily adjacent,
arr -> arr[0]
arr[1]
arr[0] -> arr[0][0]
arr[0][1]
arr[1] -> arr[1][0]
arr[1][1]
You will immediately notice that this requires more memory than the equivalent C array, and is slower to evaluate at runtime. On the other hand, it does allow the rows of an array to have different lengths.
The types char[10][10] and char** and char (*)[10] are all different types. However, the first one cannot convert into the second one, it can convert into the third one.
So try this:
char arr[10][10];
char (*ptr)[10];
ptr = arr; //ok
It will work, because as I said object of type char[10][10] can convert into an object of type char (*)[10]. They're compatible types.
I thought arrays in c++ were just pointers.
No, an array is a set of objects laid out contiguously in memory. In some circumstances, they are convertible to a pointer to the first element.
So a char[][] could also be char**
No. It is convertible to a pointer to the first one-dimensional array (which is the type char (*)[10] mentioned in the error message); but that array is not a pointer, so it is not convertible to a pointer-to-pointer.
The error exactly tells you whats wrong a double dimensional array can be assigned to an pointer to array not an double pointer. So what you need is:
char (*ptr)[10] = arr;
What am I doing wrong?
First things first
Arrays are not pointers!! but they act sometimes like pointers.
The rule is:
An expression with array type (which could be an array name) converts to a pointer anytime an array type is not legal, but a pointer type is.
So if you have a single dimensional array:
char arr[10];
Then arr decays to address of the zeroth element it has the type char *.
Hence:
char *ptr = arr;
But if you have an 2 dimensional array which is essentially an array of arrays.
char arr[10][10];
Then arr decays to the pointer to an array of 10 characters.
So, In order to assign arr to something, you will need that something to match the type, which is pointer to an array of characters.
Hence:
char (*ptr)[10] = arr;
Arrays are NOT just pointers -- arrays are arrays. Arrays are not first-class types, however, so you can't use them in many places. The thing that causes your confusion is that array names CAN be implicitly converted into pointers to the array's first element, which means that you can use an array in many places where you need a pointer and it 'just works'. This, however, is not one of those places.
Arrays are not pointers (I notice a lot of books tend to make you think this, though). They are something completely different. A pointer is a memory address while an array is a contiguous set of some data.
In some cases, an array can decay to a pointer to its first element. You can then use pointer arithmetic to iterate through the contiguous memory. An example of this case would be when passing an array to a function as a parameter.
What you probably want to do here is something like:
char arr[10];
char * i = &arr[0];
Obviously you'll need to use 2D arrays and char** in your case. I'll leave that to you to figure out :)
When you cast ar[10][10] to pointer you will get a array of pointer as said above *ar[10] and not **ar.