Questions about pointers and what is/is not a pointer - c++

Questions regarding, well, ultimately pointers to pointers (I suspect). Please read the questions posed in the commented code:
void doodah(char* a);
int main() {
char d[] = "message"; // one way of assigning a string.
// char* d = "message"; // another way of assigning a string, but REM'ed out for now.
cout << d << endl; // d appears not to be a pointer because cout outputs "message", and not an address. Why is this?
doodah(d); // a function call.
}
void doodah(char* a) {
cout << a << endl; // this outputs "message" - but why?! What does 'a' mean in this context?
// cout << *a << endl; // this outputs "m" - but why?! REM'ed out for now.
}
I am utterly confused! Please help.

cout knows how to output strings when given a char *. It does not attempt to print the pointer value itself.

An array is a bunch of objects next to each other somewhere in memory. The variable you've set the array to is actually secretly a pointer to the first item in that array (shhh!).
The biggest difference between char *c and char c[] is that the latter will be a const pointer, while the former is free to change. Also, C-Strings, like the one you have set there, are null terminated, meaning that the array ends in a binary 0 so things like cout will know when to stop iterating (this is also known as a one pass last).
For more information, you can read up on this question.

This is what the pointer a looks like in memory:
-------------------------------------------------------------
| | 'm' | 'e' | 's' | 's' | 'a' | 'g' | 'e' | '\0' |
| ^ |
| | |
| --- |
| |a| |
| --- |
-------------------------------------------------------------
a is a pointer to the first element of the string. When used in the stream inserter (operator<<()) the compiler will match it with the overload that takes a stream on its left hand side and a pointer to a character on its right hand side. It will then attempt to print every character until it reaches the null byte ('\0') by evaluating characters at incremental addresses from a.
The stream prints addresses through the overload that takes a void* on its righthand side. You can cast your pointer to a void* or use the standard-provided std::addressof() function as well:
std::cout << std::addressof(a);

Related

Work with vector of struct with int** as a member [duplicate]

Activity solution[a][b];
...
Activity **mother = solution;
I want to convert 2D array of objects to pointer-to-pointer. How can I do this;
I searched it on google. however I found only one dimension array example.
A mere conversion won't help you here. There's no compatibility of any kind between 2D array type and pointer-to-pointer type. Such conversion would make no sense.
If you really really need to do that, you have to introduce an extra intermediate "row index" array, which will bridge the gap between 2D array semantics and pointer-to-pointer semantics
Activity solution[a][b];
Activity *solution_rows[a] = { solution[0], solution[1] /* and so on */ };
Activity **mother = solution_rows;
Now accessing mother[i][j] will give you access to solution[i][j].
The reason you can do this for one-dimensional arrays and not two-dimensional arrays has to do with the way in which the actual array elements are stored in memory. For one-dimensional arrays, all of the elements are stored consecutively, so the expression array[i] is equivalent to the expression *(array + i). As you can see, the array size is not needed to perform an array index operation. However, for two-dimensional arrays, the elements are stored in "row major" order, meaning that all of the elements in the zeroth row are stored first, followed by the elements in the first row, followed by the elements in the second row, etc. Therefore, the expression array[i][j] is equivalent to *(array + (i * ROW_SIZE) + j), where ROW_SIZE is the number of elements in each row. Therefore, the array's row size is needed to perform an array index operation, and casting the array variable to a pointer loses that information.
This is c++! Everything is possible! But a this is c++ so it requires some level of understanding.
To that end let's start with a simple example of 2 1-dimensional arrays: char firstName[4] = { 'J', 'o', 'n', '\0' } and char lastName[4] = { 'M', 'e', 'e', '\0' } Let's look at a possible memory layout here:
+------------+-------+
| Address | Value |
+------------+-------+
| 0x76543210 | 0x4A | <- firstName[0] - 'J'
| 0x76543211 | 0x6F | <- firstName[1] - 'o'
| 0x76543212 | 0x6E | <- firstName[2] - 'n'
| 0x76543213 | 0x00 | <- firstName[3] - '\0'
+------------+-------+
| 0x76543214 | 0x4D | <- lastName[0] - 'M'
| 0x76543215 | 0x65 | <- lastName[1] - 'e'
| 0x76543216 | 0x65 | <- lastName[2] - 'e'
| 0x76543217 | 0x00 | <- lastName[3] - '\0'
+------------+-------+
Given this memory layout if you were to do cout << firstName << ' ' << lastName you'd get:
0x76543210 0x76543214
These arrays are really just a pointer to their first element! This illustrates Array to Pointer Decay, which you can read more about here: http://en.cppreference.com/w/cpp/language/array#Array-to-pointer_decay
Before we move on there's something important here to note, chars take up exactly 1-byte so the address of each subsequent char in the array will simply be the next address. That's leveraged by the Subscript Operator in this way: firstName[1] is equivalent to *(firstName + 1). This is true for chars but is also true for any other type which takes up more than 1-byte. Let's take for example: short siArray = { 1, 2, 3, 4 }, a possible memory layout of siArray would look like:
+------------+--------+
| Address | Value |
+------------+--------+
| 0x76543218 | 0x0001 | <- siArray[0] - 1
| 0x7654321A | 0x0002 | <- siArray[1] - 2
| 0x7654321C | 0x0003 | <- siArray[2] - 3
| 0x7654321E | 0x0004 | <- siArray[3] - 4
+------------+--------+
Even though cout << siArray << ' ' << &(siArray[1]) will output:
0x76543218 0x7654321A
*(siArray + 1) will still index the same element of siArray as siArray[1]. This is because when doing pointer arithmetic c++ considers the type of the address being operated on, thus incrementing a short* will actually increase the address by sizeof(short). You can read more about pointer arithmetic here: http://en.cppreference.com/w/cpp/language/operator_arithmetic
Lastly let's look at how c++ stores 2-dimensional arrays. Given: char name[2][4] = { { 'J', 'o', 'n', '\0' }, { 'M', 'e', 'e', '\0' } } a possible memory layout would be:
+------------+-------+
| Address | Value |
+------------+-------+
| 0x76543220 | 0x4A | <- name[0][0] - 'J'
| 0x76543221 | 0x6F | <- name[0][1] - 'o'
| 0x76543222 | 0x6E | <- name[0][2] - 'n'
| 0x76543223 | 0x00 | <- name[0][3] - '\0'
| 0x76543224 | 0x4D | <- name[1][0] - 'M'
| 0x76543225 | 0x65 | <- name[1][1] - 'e'
| 0x76543226 | 0x65 | <- name[1][2] - 'e'
| 0x76543227 | 0x00 | <- name[1][3] - '\0'
+------------+-------+
Since we know an 1-dimensional array value is really just a pointer, we can see from this memory layout that name[0] is not a pointer, it's just the first character of the first array. Thus name does not contain 2 1-dimensional array pointers, but contains the contents of the 2 arrays. (Incidentally on a 32-bit machine not storing the pointers saves 8-bytes of memory, which is pretty substantial for an 8-byte 2-dimensional array.) Thus trying to treat name as a char** would try to use the characters as a pointer.
Having understood this we really just need to avoid using c++'s pointer arithmetic to find dereference the value. To do that we'll need to work with a char* so that adding 1 is really just adding 1. So for example:
const short si2DArray[2][3] = { { 11, 12, 13 }, { 21, 22, 23 } };
const auto psi2DPointer = reinterpret_cast<const char*>(si2DArray);
for(auto i = 0U; i < size(si2DArray); ++i) {
for(auto j = 0U; j < size(*si2DArray); ++j) {
cout << *reinterpret_cast<const short*>(psi2DPointer + i * sizeof(*si2DArray) + j * sizeof(**si2DArray)) << '\t';
}
cout << endl;
}
Live Example
Note that in this example even though I reference si2DArray thought psi2DPointer I'm still using information from si2DArray to do the indexing, namely:
How many arrays are in the major dimension: size(si2DArray)
How many elements are in the minor dimension: size(*si2DArray)
What is the size in memory of the minor dimension: sizeof(*si2DArray)
What is the element type of the array: sizeof(**si2DArray)
You can thus see that the loss of information from converting from an array to a pointer is substantial. You may be tempted to preserve the element type, thereby also simplifying the pointer arithmetic. It's worthwhile to note that only a conversion to char* is considered defined behavior by reinterpret_cast: http://en.cppreference.com/w/cpp/language/reinterpret_cast#Type_aliasing
I want to convert 2D array of objects to pointer-to-pointer. How can I do this?
Why? Is it because an interface expects a pointer to pointers?
If so, you'll need to create a new array that contains those pointers.
Activity solution[a][b];
Activity* solutionPtrs[a];
for (int i = 0; i < a; ++i)
solutionPtrs[a] = solution[a];
Activity** mother = solutionPtrs;
Why can't you just cast a 2D array of T to T**? Well, because they have nothing to do with one another!
You can cast a T[a] to a T* because you get a pointer to the first element of the array.
You can do this with 2D arrays as well, but if you have a T[a][b] then it decays to a (T[b])* because a 2D array is not an array of pointers, it's an array of arrays.
Not sure if you were looking for something like this. You should provide more details about what you want to achieve. They are fundamentally different types. One solution is to below.
For the record, if someone finds it useful:
// define matrix
double A[3][3] = {
{ 1, 2, 3},
{ 4, 5, 6},
{ 7, 8, 9}
};
// allocate memory
double ** A_ptr = (double **) malloc(sizeof (double *) * 3);
for (int i = 0; i < 3; i++)
A_ptr[i] = (double *) malloc(sizeof (double) * 3);
// copy matrix
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
A_ptr[i][j] = A[i][j];
printf(" %f ", A_ptr[i][j]);
}
}
You can't. They are fundamentally different types.

C++ and C-string variables, char array size

I've searched through many articles on here and have self-tested this concept with my own code. My question is to satisfy my own curiosity and maybe help others as I cannot find a answer describing this concept in particular. My textbook (teaching C++) describes a C-string variable:
A C-string variable is an array of characters. The following array declaration provides a C-string variable "s" capable of storing a
C-string value with nine or fewer characters:
char s[10];
The 10 is for the nine letters in the string plus the null character '\0' to mark the end of the string. Like any other partially filled
array, a C-string variable uses positions starting at indexed variable
0 through as many as are needed.
I'm trying to understand the above. If the array size is 10, wouldn't the total storage size be 11? i.e. 0-10 = 11 spaces. If the \0 character occupies one space, then we'd still be able to store 10 characters and not 9 as per the book.
In my own testing, I declared a character array test[4] and stored the word "cat" in the array. When looking at individual positions within the array, I can see individual characters at each index i.e:
test[0] = c
test[1] = a
test[2] = t
test[3] =
test[4] =
Why do we need 2 additional slots in the character array and not 1?
An array with size N has indexes starting at 0 and ending with N-1. It does not have an element with index N.
With your example of char test[4], the array has indexes 0, 1, 2, and 3. Attempting to access index 4 is going off the end of the array. C and C++ do no prevent you from doing so, and attempting to do so invokes undefined behavior.
You can look at an array as a group of variables of the same type and size which are consecutive in memory one next to the other.
Arrays are indexed from 0 as the first element to the n - 1 as the last element. So you can access any element just using an index.
Trying to access an array with an index i >= n or a negative index i < 0 Will issue in undefined behavior.
Arrays of characters need to set the last element as a NULL character \0.
Here is an example:
char c[5] = "Hello"; // Error
Above c has 5 elements and \0 so it is 6 Byte long. So to correct it:
char c[6] = "Hello"; // Null character added automatically
// char c[] = "Hello";
Look at this example:
char text[6] = {'H', 'e', 'l', 'l', 'o', '\0'};
Above in a such initialization you must add the null terminator character '\0' otherwise you'll get a garbage characters at the end of your string.
std::cout << text[0]; // H which is the first element
std::cout << text[6 - 1 - 1]; // o which is the last character in the array.
arrays of other types other than characters need not to add a null terminator and the number of elements is n but indexing is the same 0 through n - 1;
int array[5] = {4, 5, 9, 22, 16};
std::cout << array[0]; // 4
std::cout << array[5 - 1]; // 16
I think your problem comes from the misconception of how you access the memory.
s[n] refers at accessing the value pointed by the pointer s plus n blocks in memory, it can also be written *(s + n)
So basically, declaring
char s[4];
and setting cat in it, you will get this layout in memory
+---+
s: | c | s[0] also (s + 0)
+---+
| a | s[1] also (s + 1)
+---+
| t | s[2] also (s + 2)
+---+
|\0 | s[3] also (s + 3)
+---+
| ? | s[4] also (s + 4)
+---+
| ? | s[5] also (s + 5)
+---+
| ? | s[6] also (s + 6)
+---+
| ? | s[7] also (s + 7)
+---+
| ? | s[8] also (s + 8)
+---+
| ? | s[9] also (s + 9)
+---+
The ? stand for a variable which we aren't sure of the value.
You CAN access it, you can even modify it sometimes.
But the behavior of this isn't clear and can be undefined.
For your example s[4] can change each time the executable is executed.
char s[10]; had valid indices from 0 to 9 and not 0 to 10 as you said.
A C-string variable is an array of characters.
This is slightly misleading. A C string is a sequence of character values followed by a 0-valued terminator. For example, the string "Hello" is represented as the sequence {'H','e', 'l', 'l', 'o', 0}. The presence of the 0 terminator makes the character sequence a string. All C string handling functions (strcat, strcmp, strcpy, strchr, etc.) assume the presence of that terminator; if the terminator isn't there, those routines will not function properly.
Strings are stored in arrays of character type (char for ASCII, EBCDIC, or UTF-8 strings or wchar_t for "wide" strings1). Multiple strings may be stored in a single array if there's sufficient space. A 10-element array may store a single 9-character string, or two 4 character strings, or 5 one-character strings. Remember that to store an N-character string you need N+1 array elements to account for the terminator.
I'm trying to understand the above. If the array size is 10, wouldn't the total storage size be 11? i.e. 0-10 = 11 spaces.
Total storage size is 10, but array elements are indexed from 0 to 9. Given the declaration
char foo[10];
you get the following layout in memory:
+---+
foo: | | foo[0]
+---+
| | foo[1]
+---+
| | foo[2]
+---+
| | foo[3]
+---+
| | foo[4]
+---+
| | foo[5]
+---+
| | foo[6]
+---+
| | foo[7]
+---+
| | foo[8]
+---+
| | foo[9]
+---+
For any N-element array, individual elements are indexed from 0 through N-1.
Remember that in C, the array subscript operation a[i] is defined as *(a + i) - given a starting address a2, offset i elements (not bytes!!!) from that address and dereference the result. The first element is stored at a, the second element is stored at a + 1, the third at a + 2, etc.
wchar_t was introduced to represent character sets outside the ranges defined by ASCII or EBCDIC, so it's wider than the `char` type (often the width of two `char`s). With the advent of schemes like UTF-8 to represent non-English character sets, it's not that useful and I don't see it used very often.
At some point, you're going to hear someone say "an array is just a pointer". This is not correct. Under most circumstances, an expression of array type will be converted ("decay") to an expression of pointer type, and the value of the expression will be the address of the first element in the array. The array object itself is not a pointer, nor does it set aside any space for a pointer value.
char test[4] is the definition of your array, it means your array's size is four, but you can only use the spaces: test[0], test[1], test[2], test[3].
You can go to http://www.cplusplus.com/doc/tutorial/arrays/ to learn more about Arrays of c++.

Issue with a char* array

Okay so I have:
char* arr[5];
and I have
char input[10];
and then:
int i = 0;
cin.getline(input, 10);
while(input[0] != 'z')
{
arr[i] = input;
cin.getline(input, 10);
i++;
}
the result is that every element in arr is the same because they are all pointers to input, but I want each element to point to char arrays that the input variable held at that given time.
result that this brings:
arr[0] = line beginning in 'z' (because that is what input currently is holding)
arr[1] = line beginning in 'z'
arr[2] = ... and so on
result that I want:
arr[0] = first line read in
arr[1] = second line read in
arr[2] = third line read in and so on...
I am confused about how I can get the elements to all point to new values instead of all be pointing to the same value.
If you want to take input 5 times,you can try this code segment
int i = 0;
while(i<5)
{
arr[i] = input;
cin.getline(input, 10);
i++;
}
this should work and you can get your "desired result" as you stated above.
Edit:
This will not work, as described in the comment. See example here: http://ideone.com/hUQGa7
What is required are different pointer values occupying each of the elements in arr. How to achieve those different pointer values is discussed in the other answers given.
Let's talk characters and pointers.
Given a character:
+---+
+ A +
+---+
A pointer to the character, char *, points to the character. That's it, nothing more.
An array of characters is a container that has slots for characters. A pointer to the array often points to the first character of the array. Here's where the problem comes in.
Many functions require a pointer, to the first character of the array, but either don't say that it's to the first character or require a pointer to a single character, assuming that the pointer is the first character in the array.
Pointers need something to Point at
You have allocated an array of pointers, but haven't allocated the memory for each pointer:
Array
+-----+ +----+---+---+
| | --> | | | |
| | +----+---+---+
+-----+
| | +----+---+---+
| | --> | | | |
| | +----+---+---+
+-----+
The content of the array are pointer. So you will need to allocate memory and place the pointer into the array:
arr[0] = new char [11]; // +1 for the nul terminator character.
char text[33];
arr[1] = text;
So what you aim to do is:
cin.getline(arr[0], 10);
cin.getline(arr[1], 33);
Strings are soooo much easier to deal with. They manage their own memory:
std::string array_text[5]; // An array of 5 string.
getline(cin, array_text[0]);
The next step is to use a vector and you are all caught up:
std::vector< std::string > text_vector(5); // Pre-allocate 5 slots.
getline(cin.text_vector[2]);
You have to copy the data of input everytime.
You can do like this in while loop:
while(input[0] != 'z')
{
arr[i] = new char[strlen(input)];
strcpy(arr[i], input);
cin.getline(input, 10);
i++;
}
And since you have defined arr to be of length 5. So you have to check in the while loop that i doesn't exceed the value 5. i<5.

Accessing the value pointed by a pointer

Edit: This question should be considered abandoned. I have flagged this question for deletion as i do not know how to even proceed any more at this point. I thank all of you for your willingness and taking the time out of your day to help me.
I am reading and following the documentation at cplusplus on data structures. I have been trying to figure out why the compiler will not accept " *pfruit.weight; " on my own for hours. It am sure it is something simple that i am missing.
error C2228: left of '.weight' must have class/struct/union
1> type is 'product *'
1> did you intend to use '->' instead?
"The operand to the left of the period (.) is not a class, structure, or union."
So how do i correctly access the value pointed by a pointer member?(Not access a reference)
#include <iostream>
using namespace std;
struct product
{
int weight;
float price;
} ;
int main ()
{
product afruit;
product * pfruit;
pfruit = &afruit;
pfruit->weight;
//Access a member of an object to which we have a reference
//equivalent to: (*pfruit).weight
*pfruit.weight; //<------ I am so sorry, i meant This is the problem, i am using a reworded line of code from an example and it isn't compiling and returning the error.
//Access the value pointed by a pointer member called weight;
//equivalent to: *(pfruit.weight)
system("pause");
return 0;
}
This code
struct product
{
int weight;
float price;
} ;
int main ()
{
product * pfruit;
*pfruit.weight;
is an operator precedence error. The rules of C++ are that . has higher precedence than *. *pfruit.weight would be correct if pfruit was a struct and weight was a pointer, but in your code it's the other way around, pfruit is the pointer and weight is just an int. So you need to add brackets to apply the operators the right way around
(*pfruit).weight;
You may use the following statement :
(*pfruit).weight;
Instead of :
*pfruit.weight;
which evaluates at compile-time to the following because of operator precedence :
*(pfruit.weight)
This is wrong because you are dereferencing a non-pointer value and trying
to dereference a pointer with the . operator instead of ->.
EDIT :
Here's some piece of response and informations about pointers and to your question as I understood it.
#include <iostream>
using namespace std;
struct product
{
int *weight;
float price;
};
int main()
{
product afruit;
product *pfruit;
pfruit = &afruit;
// Allocating 10 * sizeof(int) bytes of memory. ptr will now point to the first sizeof(int) bytes
// of the memory pointed by the weight pointer.
pfruit->weight = new int[10];
// The first sizeof(int) bytes of the memory pointed by ptr (equivalent to *ptr) equals now the value 4.
pfruit->weight[0] = 4;
// The second sizeof(int) bytes of memory pointed by ptr (or (*ptr + 1)) equals now 42.
pfruit->weight[1] = 42;
// Dereferencing pfruit AND the pointer to the weight, thus returning the VALUE of the first sizeof(int) bytes of weight (4)
// instead of the value of the pointer to weight (0x8b4e008 for instance).
int value = *(pfruit->weight);
std::cout << "Value of pfruit->weight[0] = " << pfruit->weight[0] << std::endl
<< "Value of pfruit->weight[1] = " << pfruit->weight[1] << std::endl
<< "Value of *(pfruit->weight) = " << *(pfruit->weight) << std::endl
<< "Value of *(pfruit->weight + 1) = " << *(pfruit->weight + 1) << std::endl
<< "Value of ptr = " << std::hex << pfruit->weight << std::endl;
// Prints :
// Value of pfruit->weight[0] = 4
// Value of pfruit->weight[1] = 42
// Value of *(pfruit->weight) = 4
// Value of *(pfruit->weight + 1) = 42
// Value of ptr = 0x8b4e008
//
// Note that ptr[0] == *ptr and ptr[1] == (*ptr + 1)
return (0);
}
once try this u may get it this can be written as pfruit->weight or (*pfruit).weight
(*pfruit).weight;
product afruit;
product * pfruit;
pfruit = &afruit;
pfruit->weight;
pfruit is a pointer and has the address of the struct afruit.
We use pfruit->weight when we access struct members using a pointer .
When you use a struct name you use . operator.
Now, pfruit is the pointer . Therefore, the struct itself is *pfruit
*pfruit.weight;
This is interpreted as *(pfruit.weight), because .has higher precedence than *. and you can't use . operator with a pointer on LHS
You have to clearly show that you mean (*pfruit).weight
Bit late to the party, but try this:
It sounds like you are expecting values like 'int weight' to be stored as pointers to data somewhere else in the same way that the product is being referred to via pfruit. Some languages do do this, but in C++ simple data members like your weight and price are going to be stored actually in the product data structure. So, if afruit happens to exist at address 1000 in memory, then pfruit will have the value 1000:
... 1000 1001 1002 1003 ...
--+-----+-----+-----+-----+--
| afruit... | | |
--+-----+-----+-----+-----+--
^
|
pfruit = 1000
This means that your weight (int) and price (float) data members will be stored here, one after the other. (and since an int and float are typically 32 bits in size, i.e. 4 bytes, the memory looks like this:
... 1000 1001 1002 1003 1004 1005 1006 1007 ...
--+-----+-----+-----+-----+-----+-----+-----+-----+--
| afruit... |
| <------ weight -----> | <------ price ------> |
--+-----+-----+-----+-----+-----+-----+-----+-----+--
^
|
pfruit = 1000
Consequently, pfruit also happens to point at the weight data (because it's first in the structure), but the price data is 4 bytes further along.
So, when you say you want to get to the data 'pointed to by weight' it doesn't make sense because it actually turns out that you don't need to because when you access the weight member you are already referring to the weight value. It's right there, in the memory occupied by afruit.
If you ARE trying to get a pointer TO the weight (or cost) data itself (instead of afruit, or actually from pfruit) you can do something like this:
int* pweight = &afruit.weight; //from an actual product object
float* pcost = &pfruit->cost; //via a pointer to a product object
There are now various ways to access the members of the product structure afruit:
afruit.weight = 20; //directly access the structure member
pfruit->weight = 10; //follow the structure pointer
*pweight = 15; //derefernce the int pointer
I hope this helps someone, at least a little bit.
Sam

conversion of 2D array to pointer-to-pointer

Activity solution[a][b];
...
Activity **mother = solution;
I want to convert 2D array of objects to pointer-to-pointer. How can I do this;
I searched it on google. however I found only one dimension array example.
A mere conversion won't help you here. There's no compatibility of any kind between 2D array type and pointer-to-pointer type. Such conversion would make no sense.
If you really really need to do that, you have to introduce an extra intermediate "row index" array, which will bridge the gap between 2D array semantics and pointer-to-pointer semantics
Activity solution[a][b];
Activity *solution_rows[a] = { solution[0], solution[1] /* and so on */ };
Activity **mother = solution_rows;
Now accessing mother[i][j] will give you access to solution[i][j].
The reason you can do this for one-dimensional arrays and not two-dimensional arrays has to do with the way in which the actual array elements are stored in memory. For one-dimensional arrays, all of the elements are stored consecutively, so the expression array[i] is equivalent to the expression *(array + i). As you can see, the array size is not needed to perform an array index operation. However, for two-dimensional arrays, the elements are stored in "row major" order, meaning that all of the elements in the zeroth row are stored first, followed by the elements in the first row, followed by the elements in the second row, etc. Therefore, the expression array[i][j] is equivalent to *(array + (i * ROW_SIZE) + j), where ROW_SIZE is the number of elements in each row. Therefore, the array's row size is needed to perform an array index operation, and casting the array variable to a pointer loses that information.
This is c++! Everything is possible! But a this is c++ so it requires some level of understanding.
To that end let's start with a simple example of 2 1-dimensional arrays: char firstName[4] = { 'J', 'o', 'n', '\0' } and char lastName[4] = { 'M', 'e', 'e', '\0' } Let's look at a possible memory layout here:
+------------+-------+
| Address | Value |
+------------+-------+
| 0x76543210 | 0x4A | <- firstName[0] - 'J'
| 0x76543211 | 0x6F | <- firstName[1] - 'o'
| 0x76543212 | 0x6E | <- firstName[2] - 'n'
| 0x76543213 | 0x00 | <- firstName[3] - '\0'
+------------+-------+
| 0x76543214 | 0x4D | <- lastName[0] - 'M'
| 0x76543215 | 0x65 | <- lastName[1] - 'e'
| 0x76543216 | 0x65 | <- lastName[2] - 'e'
| 0x76543217 | 0x00 | <- lastName[3] - '\0'
+------------+-------+
Given this memory layout if you were to do cout << firstName << ' ' << lastName you'd get:
0x76543210 0x76543214
These arrays are really just a pointer to their first element! This illustrates Array to Pointer Decay, which you can read more about here: http://en.cppreference.com/w/cpp/language/array#Array-to-pointer_decay
Before we move on there's something important here to note, chars take up exactly 1-byte so the address of each subsequent char in the array will simply be the next address. That's leveraged by the Subscript Operator in this way: firstName[1] is equivalent to *(firstName + 1). This is true for chars but is also true for any other type which takes up more than 1-byte. Let's take for example: short siArray = { 1, 2, 3, 4 }, a possible memory layout of siArray would look like:
+------------+--------+
| Address | Value |
+------------+--------+
| 0x76543218 | 0x0001 | <- siArray[0] - 1
| 0x7654321A | 0x0002 | <- siArray[1] - 2
| 0x7654321C | 0x0003 | <- siArray[2] - 3
| 0x7654321E | 0x0004 | <- siArray[3] - 4
+------------+--------+
Even though cout << siArray << ' ' << &(siArray[1]) will output:
0x76543218 0x7654321A
*(siArray + 1) will still index the same element of siArray as siArray[1]. This is because when doing pointer arithmetic c++ considers the type of the address being operated on, thus incrementing a short* will actually increase the address by sizeof(short). You can read more about pointer arithmetic here: http://en.cppreference.com/w/cpp/language/operator_arithmetic
Lastly let's look at how c++ stores 2-dimensional arrays. Given: char name[2][4] = { { 'J', 'o', 'n', '\0' }, { 'M', 'e', 'e', '\0' } } a possible memory layout would be:
+------------+-------+
| Address | Value |
+------------+-------+
| 0x76543220 | 0x4A | <- name[0][0] - 'J'
| 0x76543221 | 0x6F | <- name[0][1] - 'o'
| 0x76543222 | 0x6E | <- name[0][2] - 'n'
| 0x76543223 | 0x00 | <- name[0][3] - '\0'
| 0x76543224 | 0x4D | <- name[1][0] - 'M'
| 0x76543225 | 0x65 | <- name[1][1] - 'e'
| 0x76543226 | 0x65 | <- name[1][2] - 'e'
| 0x76543227 | 0x00 | <- name[1][3] - '\0'
+------------+-------+
Since we know an 1-dimensional array value is really just a pointer, we can see from this memory layout that name[0] is not a pointer, it's just the first character of the first array. Thus name does not contain 2 1-dimensional array pointers, but contains the contents of the 2 arrays. (Incidentally on a 32-bit machine not storing the pointers saves 8-bytes of memory, which is pretty substantial for an 8-byte 2-dimensional array.) Thus trying to treat name as a char** would try to use the characters as a pointer.
Having understood this we really just need to avoid using c++'s pointer arithmetic to find dereference the value. To do that we'll need to work with a char* so that adding 1 is really just adding 1. So for example:
const short si2DArray[2][3] = { { 11, 12, 13 }, { 21, 22, 23 } };
const auto psi2DPointer = reinterpret_cast<const char*>(si2DArray);
for(auto i = 0U; i < size(si2DArray); ++i) {
for(auto j = 0U; j < size(*si2DArray); ++j) {
cout << *reinterpret_cast<const short*>(psi2DPointer + i * sizeof(*si2DArray) + j * sizeof(**si2DArray)) << '\t';
}
cout << endl;
}
Live Example
Note that in this example even though I reference si2DArray thought psi2DPointer I'm still using information from si2DArray to do the indexing, namely:
How many arrays are in the major dimension: size(si2DArray)
How many elements are in the minor dimension: size(*si2DArray)
What is the size in memory of the minor dimension: sizeof(*si2DArray)
What is the element type of the array: sizeof(**si2DArray)
You can thus see that the loss of information from converting from an array to a pointer is substantial. You may be tempted to preserve the element type, thereby also simplifying the pointer arithmetic. It's worthwhile to note that only a conversion to char* is considered defined behavior by reinterpret_cast: http://en.cppreference.com/w/cpp/language/reinterpret_cast#Type_aliasing
I want to convert 2D array of objects to pointer-to-pointer. How can I do this?
Why? Is it because an interface expects a pointer to pointers?
If so, you'll need to create a new array that contains those pointers.
Activity solution[a][b];
Activity* solutionPtrs[a];
for (int i = 0; i < a; ++i)
solutionPtrs[a] = solution[a];
Activity** mother = solutionPtrs;
Why can't you just cast a 2D array of T to T**? Well, because they have nothing to do with one another!
You can cast a T[a] to a T* because you get a pointer to the first element of the array.
You can do this with 2D arrays as well, but if you have a T[a][b] then it decays to a (T[b])* because a 2D array is not an array of pointers, it's an array of arrays.
Not sure if you were looking for something like this. You should provide more details about what you want to achieve. They are fundamentally different types. One solution is to below.
For the record, if someone finds it useful:
// define matrix
double A[3][3] = {
{ 1, 2, 3},
{ 4, 5, 6},
{ 7, 8, 9}
};
// allocate memory
double ** A_ptr = (double **) malloc(sizeof (double *) * 3);
for (int i = 0; i < 3; i++)
A_ptr[i] = (double *) malloc(sizeof (double) * 3);
// copy matrix
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
A_ptr[i][j] = A[i][j];
printf(" %f ", A_ptr[i][j]);
}
}
You can't. They are fundamentally different types.