Allocating memory specified by a reference variable for nested arrays? - c++

I am supposed to implement a function
void foo(string** &grid);
Where I populate the given reference with a freshly allocated array or array of strings, I'd imagine.
I've done things like
void foo(string** &grid) {
grid = new string[4][4];
}
But I get this error:
error: cannot convert 'std::string (*)[4] {aka std::basic_string<char> (*)[4]}' to 'std::string** {aka std::basic_string<char>**} in assignment
Hm.
I see what this error is trying to tell me, but what is my fundamental misunderstanding here, and how would I go about doing what I want to do?
Thank you

new string[4][4] creates a pointer to string[4], not a pointer to pointer to string. The closest you can get is something like this:
grid = new string*[4];
for (int i = 0; i < 4; i++) {
grid[i] = new string[4];
}
But note that the 16 strings created in the process might not all be stored contiguously in memory.

Related

C++: Type of multidimensional array with `variable` size

I can run this
int a = 5;
auto foo = new int [a][4][4];
But when I try this:
int a = 5;
int * foo[4][4];
foo = new int [a][4][4];
I get the error
error: incompatible types in assignment of ‘int (*)[4][4]’ to ‘int* [4][4]’
Question
What type do I have to specify for foo?
Edit:
The goal is to have one single chunk of memory, not an array of pointers.
The error message is a little confusing because it does not state the variable name.
This works:
int a = 5;
int (*foo)[4][4];
foo = new int [a][4][4];
As #john correctly identified:
You're confused between a 2D array of pointers (that's what you wrote) and a pointer to a 2D array (that's what you want).
So what's the difference between pointer to an array and array of pointers. The correct syntax to define a pointer to an array (what you tried to do):
data_type (*var_name)[array_size];
But this defines an array of pointers (what you actually did):
data_type *var_name[array_size];
#OP in your own answer you already found out what the correct type should be – a pointer to an array int (*foo)[4][4], but I thought a little more explanation is also helpful.

Pass the previously assigned pointer value to a loop

I've got a string pointer string* ifxPtr;, what I'm trying to do is to set this pointer to point to the user input and then loop through each character of it.
string* ifxPtr;
void Expression::GetInfix(string data) // This method runs first and it's setting the pointer to point to previously passed user input
{
ifxPtr = &data;
ConvertToPostfix();
}
void Expression::ConvertToPostfix()
{
for (int i = 0; i < *ifxPtr->length; i++) // Here's the struggle, compiler is complaining about *ifxPtr with message Cannot apply binary '<' to 'int' and 'unassigned() const'
{
//Do something here
}
}
length is a function and it should be length()
You
don't need to deference the pointer if you use ->
The result
returned from length() is size_t
Here is what I would use:
int length = static_cast<int>((*ifxPtr).length());
foo-> is shorthand for (*foo).. Don't double up operators, also it should be length():
for (int i = 0; i < ifxPtr->length(); i++)
Also, be careful with that design, possibility of running into Undefined Behaviour with a simple mistake is big.
if you use and *before it means using the value which is pointed by the pointer.
string s,*p;
p=&s;
here *p.lenght() is same as s.length if you want to access through pointer you have to use it like this p->length().

Cannot assign integer to dynamically allocated 2D array

I have created a 2D-array in following way:
int** map_array = (int**)malloc(sizeof(yy_value*xx_value));
When i try to assign a value on a position:
map_array[y*xx_value+x] = 5;
I get following error:
Assigning to 'int *' from incompatible type 'int'
What am i doing wrong here?
Change:
int** map_array = (int**)malloc(sizeof(yy_value*xx_value));
to:
int* map_array = (int*)malloc(yy_value*xx_value*sizeof(map_array[0]));
Explanation: you're allocating a "flattened" 2D array here, where you calculate your own 1D index rather than an actual 2D array. Also the size passed to malloc was incorrect.
Note that you should probably not be using malloc in a C++ program without a good reason.
you can alternatively use a 2D array as:
int **map_array = (int**)malloc(xx_value*sizeof(int*))
for (i = 0; i < xx_value; i++) {
map_array[i] = (int*)malloc(yy_value*sizeof(int))
}
and access elements using:
map_array[x][y] = 5;

Dynamic array and void pointers

I have quite peculiar problem. I want initialize an array pointed by a void pointer to which memory is allocated using new as shown below.
const int ARRAY_SIZE = 10;
void InitArray()
{
int *ptrInt = new int[ARRAY_SIZE];
for(int i=0; i<ARRAY_SIZE;i++)
{
ptrInt[i] = 1; //OK
}
void *ptrVoid = new int[ARRAY_SIZE];
for(int i=0; i<ARRAY_SIZE;i++)
{
*(int*)ptrVoid[i] = 1; //Culprit : I get a compiler error here
//(error C2036: 'void *' : unknown size)
}
}
Now, I want to initialize the elements of this array which is pointed by ptrVoid with say 1. How do I go about it? With this code I get a compiler error as shown in the code(I am using VS 2010). Any suggestions?
You have an order of operations problem (and an extra *). Try this inside your second loop:
((int *)ptrVoid)[i] = 1;
*(int*)ptrVoid[i] is *((int*)(ptrVoid[i])), and you're dereferencing too many times (the [] does a dereference).
Write ((int*)ptrVoid)[i] (or, better, static_cast<int*>(ptrVoid)[i]) then re-consider your use of void* at all.
You just need to parenthesize correctly and cast the void* to an int*, so that the compiler knows how many bytes to offset when you index it with [i].
for(int i=0; i<ARRAY_SIZE;i++)
{
((int*)ptrVoid)[i] = 1;
}
How about:
int* ptrVoidAsInt = new int[ARRAY_SIZE];
for(int i=0; i<ARRAY_SIZE;i++)
{
ptrVoidAsInt[i] = 1;
}
void* ptrVoid = ptrVoidAsInt;
But, one has to wonder what the meaning of either a void array or 1 initialised data is. Is this really an array of int or some other type that is going to be passed as a void* and then recast back to a typed array?

return 2d array from function in C++

I have a function declared like so:
unsigned char** Classifier::classify(){
//...
unsigned char **chars = new unsigned char *[H];
for(int i = 0; i < H; i++)
chars[i] = new unsigned char[W*3];
//...
return &chars;
//note: when this is "return chars;" I get the following: cannot convert ‘unsigned char*’ to ‘unsigned char**’ in return
This is giving me the warning:
Classifier.cpp: In member function ‘unsigned char** Classifier::classify()’:
Classifier.cpp:124: warning: address of local variable ‘chars’ returned
Is this ok to ignore? Basically, my question is how do you return a reference to an array that is defined in the function?
I want to be able to do
unsigned char** someData = classify();
Just return the array, not its address:
return chars;
&chars is a pointer to a pointer to a pointer, but chars is a pointer to a pointer (what you want). Also note that chars is not an array. Pointers and arrays are not the same thing, although they are often confused.
This is never okay to ignore. You're returning the address of a local variable. That address will become invalid when you leave classify()'s stack frame, before the caller has a chance to use it.
You only need to return the value of that variable instead:
return chars;
#Adam Rosenfield has got the correct answer and so have some others, (remove that ampersand) but as food for thought, a nice way to do this is to use a std::vector (of std::vectors) and pass it into the function as a reference parameter.
#include <vector>
void Classifier::classify(std::vector<std::vector<unsigned char>> & chars)
{
//construct a vector of W*3 integers with value 0
//NB ( this gets destroyed when it goes out of scope )
std::vector<unsigned char> v(W*3,0);
//push a copy of this vector to the one you passed in - H times.
for(int i = 0; i < H; i++)
chars.push_back(v);
}
chars is populated with the stuff you want and when it comes to deleting the vector, you don't have to worry about how to call the correct delete[] syntax that you would with those two calls to new in your 2D array.
You can still reference items in this vector as you would with your 2D array e.g. chars[5][2] or whatever.
although I can see you want to be able to go:
unsigned char** someData = classify();
So if you wanted to use vectors, you'd have to declare someData as follows:
std::vector<std::vector<unsigned char>> someData;
and to make that clearer perhaps:
typedef std::vector<std::vector<unsigned char>> vector2D;
vector2D someData;
classify(someData);
...
If an array defined in function and if you want to use it outside the function - you should describe it (array) as static or declare an array outside the function and pass it as parameter.
Use "return chars;" only;
No, it's not okay to ignore that warning. The value you're returning is the address of chars on the stack, not the thing it points to. You want to return just chars.
Others have given teh answer; but as a general observation I would recommend you look at the STL. You've tagged the question C and C++, so I'm assuming you're in a C++ environment and the STL is available. You can then use typedefs to define vectors in a readable form , and even vectors of vectors (ie. 2d arrays). You can then return a pointer or reference (as appropriate) to your vector of vectors.