I want to pass a reference to an array from one object GameModel to another PersonModel, store reference and then work with this array inside PersonModel just like inside GameModel, but...
I have a terrible misunderstanding of passing an array process: In the class PersonModel I want to pass an array by reference in a constructor (see code block below). But the marked line throws the compile error
PersonModel::PersonModel( int path[FieldSize::HEIGHT][FieldSize::WIDTH], int permissionLevel ) {
this->path = path; //<------ ERROR here:
//PersonModel.cpp:14:22: error: incompatible types in assignment of 'int (*)[30]' to 'int [31][30]'
this->permissionLevel = permissionLevel;
}
Here is the header file PersonModel.h
#ifndef PERSON_MODEL
#define PERSON_MODEL
#include "data/FieldSize.h"
namespace game{
class IntPosition;
class MotionDirection;
class PersonModel {
protected:
int path[FieldSize::HEIGHT][FieldSize::WIDTH];
int permissionLevel;
public:
PersonModel( int path[FieldSize::HEIGHT][FieldSize::WIDTH], int permissionLevel );
void setMotionDirection ( MotionDirection* md);
void step(long time);
void reset(long time);
};
}
#endif
As I see now, I can change the int path[FieldSize::HEIGHT][FieldSize::WIDTH]; declaration to int (*path)[FieldSize::WIDTH]; but it is much more confusing.
Help me understand this topic: what is the proper way to store the passed reference to an array to work with it later, like with usual 2D array.
UPDATE:
This array is a map of game field tiles properties represented by bit-masks, so it is read-only actually. All the incapsulated objects of GameModel class should read this array, but I definitely don't want to duplicate it or add some extra functionality.
There are no frameworks just bare Android-NDK.
I think you've fallen into the classic trap of believing someone who's told you that "arrays and pointers are the same in C".
The first thing I'd do would be to define a type for the array:
typedef int PathArray[FieldSize::HEIGHT][FieldSize::WIDTH];
You then don't need to worry about confusions between reference to array of ints vs array of references to ints.
Your PersonModel then contains a reference to one of these.
PathArray &path;
and, because its a reference it must be initialised in the constructors initialization list rather than in the constructor body.
PersonModel::PersonModel( PathArray &aPath, int aPermissionLevel ) :
path(aPath),
permissionLevel(aPermissionLevel)
{
}
Of course, holding references like this is a little scary so you might want to consider using a boost::shared_ptr or something similar instead to make the lifetime management more robust.
You cannot assign arrays as you do with value types in C++
int path[x][y] resolves to the type int (*)[y]
Possible solutions are:
Using memcpy/copy
Using std::array
You can't assign to an array like that. However you can use the fact that an array is a contiguous memory area, even when having an array of arrays, and use e.g. memcpy to copy the array:
memcpy(this->path, path, FieldSize::HEIGHT * FieldSize::WIDTH * sizeof(int));
You would have to pass a pointer to the 2d-array as you cannot pass the array as you have stated in the code snippet.
I would suggest using the STL array type. Admittedly std::array is C++ '11 standard and therefore old compiler may not support it. You can also use vector which has been around longer.
vector<vector<int>>path;
You will have to resize the 2d-vector in the constructor.
Indexing would look a bit funny:
path[1].[1] ....
With vectors, you can then pass it by reference.
the name of the array is a pointer on first element
so,
you can try
PersonModel( int (*path)[FieldSize::HEIGHT][FieldSize::WIDTH], int permissionLevel );
In C++ '=' implemented for primitive types like int and double but not for array(array is not a primitive type), so you should never use '=' to assign an array to new array, instead you should use something as memcpy to copy array. memcpy copy a memory over another memory, so you can use it to copy an array over another array:
// memcpy( dst, src, size );
memcpy( this->path, path, FieldSize::HEIGHT * FieldSize * WEIGHT * sizeof(int) );
Related
I am working with propriety code in my iOS project and all I have access to is the header files for my project. How do you declare an array in C++ so that it will return an array when I make a call?
Here's the header file method,
short WI_GetIDsFromList(int32_t module, int32_t *idsArray, uint32_t *count);
How do you declare an array to received an array of in32_t? I keep getting a parameter error for returnedIdsArray when I make this call? It works perfectly fine for count? I tried making it into a pointer but it did not work?
//Array of ID's
int32_t returnedIdsArray[] = {};
// Array of ID's count
uint32_t count;
rc += WI_GetIDsFromList(mod, returnedIdsArray, &count);
Another Example
short dpCount;
//Get number of data points from the device
WI_GetDatapointCount(modIDHDS, &dpCount);
//dpCount now has returned value of method WI_GetDatapointCount
NSLog#"%d", int(dpCount);
I think Mochi's question is how to declare the array that it suits the need of the function given in the header. If I understand him right, he has no influence to the function taking the array as parameter.
Did you try:
int32_t returnedIdsArray[MaximumExpectedIds];
Maybe there is also a function in the API giving you the number of Ids that you could use to determine the array size.
You cannot pass an array in C or C++, because they will always decay to a pointer to the first element.
You can, however, pass a reference to an array. It retains its array type rather than decay to a pointer, so sizeof() will return the actual size of the array rather than the sizeof pointer, and so on.
void f(char(&charArray)[30])
{
}
Syntax is pretty ugly though. A type alias can help:
using CharArray30 = char(&)[30];
void f(CharArray30 charArray)
{
}
etc. It has restrictions, though. For example, you cannot pass arrays of a different size.
If you need your function to work with various sizes, you can use a function template with a non-type parameter for the size:
template <size_t SIZE>
void f(int32_t module, int32_t(&idArray)[SIZE])
{
// ...
}
I guess that what you are trying to do is to have the function output a set of int values where the length is not known at compile-time.
In C++ an array has a fixed size that must be known at compile-time. The concept of "runtime-sized array" is called vector in C++.
Also, it is more natural to use the return value for values being returned. Your code could look like:
std::vector<int> WI_GetIDsFromList(int32_t mod);
and the calling code could be:
auto values = WI_GetIDsFromList(mod);
I understand that this question was asked before but I don't get why it doesn't work in my case
void calc(vector<char> zodis1, vector<char> zodis2, vector<char> zodisAts,int zo1,int zo2,int zoA)
{
int i,u=0;
int zod1[zo1]=0;
int zod2[zo2]=0;
int zodA[zoA]=0;
}
All 3 of zod1, zod2, zoA gives me error: variable-sized object may not be initialized c++
But compiler should know the meaning of zo before initialization cause cout<<zo1; works and print out the meaning
So whats the problem?
You can declare an array only with constant size, which can be deduced at compile time. zo1,zo2 and zoA are variables, and the values can be known only at runtime.
To elaborate, when you allocate memory on the stack, the size must be known at compile time. Since the arrays are local to the method, they will be placed on the stack. You can either use constant value, or allocate memory in the heap using new, and deallocate when done using delete, like
int* zod1 = new int[zo1];
//.... other code
delete[] zod1;
But you can use vector instead of array here also, and vector will take care of allocation on the heap.
As a side note, you should not pass vector by value, as the whole vector will be copied and passed as argument, and no change will be visible at the caller side. Use vector<char>& zodis1 instead.
Here is the fix, you can write the following lines instead of the line where you got the error;
Alternative 1 you can use vectors:
vector<int> zod1(zo1, 0);
Alternative 2 (for example, since w know "0 <= s.length <= 100", we can use constant value):
int zod1[100] = { 0 };
I'm trying to do a little application that would calculate some paths for a given graph.
I've created a class to handle simple graphs, as follows:
class SimpleGraph {
int _nbNodes;
int _nbLines;
protected:
int AdjMatrix[_nbNodes, _nbNodes]; //Error happens here...
int IncMatrix[_nbNodes, _nbLines]; //...and here!
public:
SimpleGraph(int nbNodes, int nbLines) { this->_nbNodes = nbNodes - 1; this->_nbLines = nbLines - 1; };
virtual bool isSimple();
};
At compilation time, I get an error on the two protected members declaration.
I don't understand what is wrong, as there is only one constructor that takes these values as parameters. As such, they cannot be uninitialized.
What am I missing here?
The compiler needs to know how much space to allocate for a member of class SimpleGraph. However, since AdjMatrix and IncMatrix are defined on the stack and their sizes are determined at run-time (i.e., after compilation), it cannot do that. Specifically, the standard says that the size of an array in a class must be a constexpr.
To fix this, you can:
Allocate AdjMatrix and IncMatrix on the heap instead and then you can allocate memory at runtime.
Use a fixed size for the two arrays and keep them on the stack.
--
Another major issue with your code is that you cannot create multi-dimensional arrays using a comma (AdjMatrix[int, int]). You must instead either use:
AdjMatrix[int][int]
AdjMatrix[int * int]
Objects in C++ have a fixed size that needs to be known at compilation time. The size of AdjMatrix and InMatrix are not known at compilation time, only at run time.
In the lines
int AdjMatrix[_nbNodes, _nbNodes]; //Error happens here...
int IncMatrix[_nbNodes, _nbLines]; //...and here!
The array notation is wrong. You cannot specify a 2 dimensional array that way in C++. The correct notation uses brackets on each dimension, as for instance:
int data[5][2];
Regarding the problem you are facing, the dimensions of an array in C++ must be specified at compile time, ie. the compiler must know what are the values used to indicate the array dimension when compiling the program. This is clearly not the case here. You must revert to use integer literals, as in my example, or change the code to use vectors:
std::vector<std::vector<int> > AdjMatrix;
and in the constructor:
SimpleGraph(int nbNodes, int nbLines) : AdjMatrix(nbNodes) {
for (int i = 0; i< nbNodes; i++)
AdjMatrix[i].resize(20);
}
Note that you won't need _nbNodes anymore, and use instead the size() method on AdjMatrix. You will have to do the same for IncMatrix.
Another option, if you know the values at compile time, is to use macros to define them symbolically.
#define NBNODES 20
int AdjMatrix[NBNODES][NBNODES];
but since you wish to pass them as constructor parameter, this may not fit your need. Still, if you know that the parameters are constants at compile time, you might be able use the C++11 constexpr qualifier on the constructor parameters.
I have a struc like this:
struct process {int PID;int myMemory[];};
however, when I try to use it
process p;
int memory[2];
p.myMemory = memory;
I get an criptic error from eclipse saying int[0] is not compatible with int[2];
what am i doing wrong?
Thanks!
Don't use static arrays, malloc, or even new if you're using C++. Use std::vector which will ensure correct memory management.
#include <vector>
struct Process {
int pid;
std::vector<int> myMemory;
};
Process p;
p.reserve(2); // allocates enough space on the heap to store 2 ints
p.myMemory.push_back( 4815 ); // add an index-zero element of 4815
p.myMemory.push_back( 162342 ); // add an index-one element of 162342
I might also suggest creating a constructor so that pid does not initially have an undefined value:
struct Process {
Process() : pid(-1), myMemory() {
}
int pid;
std::vector<int> myMemory;
};
I think you should declare myMemory as an int* then malloc() when you know the size of it. After this it can be used like a normal array. Int[0] seems to mean "array with no dimension specified".
EXAMPLE:
int *a; // suppose you'd like to have an array with user specified length
// get dimension (int d)
a = (int *) malloc(d * sizeof(int));
// now you can forget a is a pointer:
a[0] = 5;
a[2] = 1;
free((void *) a); // don't forget this!
All these answers about vector or whatever are confused :) using a dynamically allocated pointer opens up a memory management problem, using vector opens up a performance problem as well as making the data type a non-POD and also preventing memcpy() working.
The right answer is to use
Array<int,2>
where Array is a template the C++ committee didn't bother to put in C++99 but which is in C++0x (although I'm not sure of the name). This is an inline (no memory management or performance issues) first class array which is a wrapper around a C array. I guess Boost has something already.
In C++, array definition is almost equal to pointer constants, meaning that their address cannot be changed, while the values which they point to can be changed. That said, you cannot copy elements of an array into another by the assignment operator. You have to go through the arrays and copy the elements one by one and check for the boundary conditions yourself.
The syntax ...
struct process {int PID;int myMemory[];};
... is not valid C++, but it may be accepted by some compilers as a language extension. In particular, as I recall g++ accepts it. It's in support for the C "struct hack", which is unnecessary in C++.
In C++, if you want a variable length array in a struct, use std::vector or some other array-like class, like
#include <vector>
struct Process
{
int pid;
std::vector<int> memory;
};
By the way, it's a good idea to reserve use of UPPERCASE IDENTIFIERS for macros, so as to reduce the probability of name collisions with macros, and not make people reading the code deaf (it's shouting).
Cheers & hth.,
You cannot make the array (defined using []) to point to another array. Because the array identifier is a const pointer. You can change the value pointed by the pointer but you cannot change the pointer itself. Think of "int array[]" as "int* const array".
The only time you can do that is during initialization.
// OK
int array[] = {1, 2, 3};
// NOT OK
int array[];
array = [1, 2, 3]; // this is no good.
int x[] is normally understood as int * x.
In this case, it is not, so if you want a vector of integers of an undetermined number of positions, change your declaration to:
struct process {int PID;int * myMemory;};
You should change your initialization to:
int memory[2];
p.myMemory = new int[ 10 ];
void pushSynonyms (string synline, char matrizSinonimos [1024][1024]){
stringstream synstream(synline);
vector<int> synsAux;
int num;
while (synstream >> num) {synsAux.push_back(num);}
int index=0;
while (index<(synsAux.size()-1)){
int primerSinonimo=synsAux[index];
int segundoSinonimo=synsAux[++index];
matrizSinonimos[primerSinonimo][segundoSinonimo]='S';
matrizSinonimos [segundoSinonimo][primerSinonimo]='S';
}
}
and the call..
char matrizSinonimos[1024][1024];
pushSynonyms("1 7", matrizSinonimos)
It's important for me to pass matrizSinonimos by reference.
Edit: took away the & from &matrizSinonimos.
Edit: the runtime error is:
An unhandled win32 exception occurred in program.exe [2488]![alt text][1]
What's wrong with it
The code as you have it there - i can't find a bug. The only problem i spot is that if you provide no number at all, then this part will cause harm:
(synsAux.size()-1)
It will subtract one from 0u . That will wrap around, because size() returns an unsigned integer type. You will end up with a very big value, somewhere around 2^16 or 2^32. You should change the whole while condition to
while ((index+1) < synsAux.size())
You can try looking for a bug around the call side. Often it happens there is a buffer overflow or heap corruption somewhere before that, and the program crashes at a later point in the program as a result of that.
The argument and parameter stuff in it
Concerning the array and how it's passed, i think you do it alright. Although, you still pass the array by value. Maybe you already know it, but i will repeat it. You really pass a pointer to the first element of this array:
char matrizSinonimos[1024][1024];
A 2d array really is an array of arrays. The first lement of that array is an array, and a pointer to it is a pointer to an array. In that case, it is
char (*)[1024]
Even though in the parameter list you said that you accept an array of arrays, the compiler, as always, adjusts that and make it a pointer to the first element of such an array. So in reality, your function has the prototype, after the adjustments of the argument types by the compiler are done:
void pushSynonyms (string synline, char (*matrizSinonimos)[1024]);
Although often suggested, You cannot pass that array as a char**, because the called function needs the size of the inner dimension, to correctly address sub-dimensions at the right offsets. Working with a char** in the called function, and then writing something like matrizSinonimos[0][1], it will try to interpret the first sizeof(char**) characters of that array as a pointer, and will try to dereference a random memory location, then doing that a second time, if it didn't crash in between. Don't do that. It's also not relevant which size you had written in the outer dimension of that array. It rationalized away. Now, it's not really important to pass the array by reference. But if you want to, you have to change the whole thingn to
void pushSynonyms (string synline, char (&matrizSinonimos)[1024][1024]);
Passing by reference does not pass a pointer to the first element: All sizes of all dimensions are preserved, and the array object itself, rather than a value, is passed.
Arrays are passed as pointers - there's no need to do a pass-by-reference to them. If you declare your function to be:
void pushSynonyms(string synline, char matrizSinonimos[][1024]);
Your changes to the array will persist - arrays are never passed by value.
The exception is probably 0xC00000FD, or a stack overflow!
The problem is that you are creating a 1 MB array on the stack, which probably is too big.
try declaring it as:
void pushSynonyms (const string & synline, char *matrizSinonimos[1024] )
I believe that will do what you want to do. The way you have it, as others have said, creates a 1MB array on the stack. Also, changing synline from string to const string & eliminates pushing a full string copy onto the stack.
Also, I'd use some sort of class to encapsulate matrizSinonimos. Something like:
class ms
{
char m_martix[1024][1024];
public:
pushSynonyms( const string & synline );
}
then you don't have to pass it at all.
I'm at a loss for what's wrong with the code above, but if you can't get the array syntax to work, you can always do this:
void pushSynonyms (string synline, char *matrizSinonimos, int rowsize, int colsize )
{
// the code below is equivalent to
// char c = matrizSinonimos[a][b];
char c = matrizSinonimos( a*rowsize + b );
// you could also Assert( a < rowsize && b < colsize );
}
pushSynonyms( "1 7", matrizSinonimos, 1024, 1024 );
You could also replace rowsize and colsize with a #define SYNONYM_ARRAY_DIMENSION 1024 if it's known at compile time, which will make the multiplication step faster.
(edit 1) I forgot to answer your actual question. Well: after you've corrected the code to pass the array in the correct way (no incorrect indirection anymore), it seems most probable to me that you did not check you inputs correctly. You read from a stream, save it into a vector, but you never checked whether all the numbers you get there are actually in the correct range. (end edit 1)
First:
Using raw arrays may not be what you actually want. There are std::vector, or boost::array. The latter one is compile-time fixed-size array like a raw-array, but provides the C++ collection type-defs and methods, which is practical for generic (read: templatized) code.
And, using those classes there may be less confusion about type-safety, pass by reference, by value, or passing a pointer.
Second:
Arrays are passed as pointers, the pointer itself is passed by value.
Third:
You should allocate such big objects on the heap. The overhead of the heap-allocation is in such a case insignificant, and it will reduce the chance of running out of stack-space.
Fourth:
void someFunction(int array[10][10]);
really is:
(edit 2) Thanks to the comments:
void someFunction(int** array);
void someFunction(int (*array)[10]);
Hopefully I didn't screw up elsewhere....
(end edit 2)
The type-information to be a 10x10 array is lost. To get what you've probably meant, you need to write:
void someFunction(int (&array)[10][10]);
This way the compiler can check that on the caller side the array is actually a 10x10 array. You can then call the function like this:
int main() {
int array[10][10] = { 0 };
someFunction(array);
return 0;
}