Example:
//
test.h
#define MAX 3
test.cpp
static char *movies[MAX] = {
"The Departed", "The Crow", "Hot Fuzz"};
//
Why not use Vector<char*>, or Vector<string*>, or an Array, or another data type?
What benefits do i have over the other data types?
Let me preface this by saying that i'm coming from the Java world andi've been learning C++ for a few months.
What benefits do i have over the other data types?
One thing to notice if using std::vector is that it will be initialized dynamically at runtime while the static const char*[max] can be initialized at compile time. So it will save some(very little though) runtime.
You will not have to directly cast the pointer to another type.. if some functions only accept the char ptr vector then you will not have any conversion to do
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);
My intention is to build such a data structure in C++:
struct callbackDataUnit {
std::string columnName;
std::string columnData;
};
std::vector<callbackDataUnit> callbackRow;
std::vector<callbackRow> callbackSet; <--- Invalid... It needs a type here
The compiler first complains about the lack os static on callbackRow. Even if I use static there, it still does not compile as the structure is naturally invalid
I would like to take this opportunity to understand a little more about C++ (I´m a beginner on that area), so here goes my questions:
a) Why do we need the static qualifier here ?
b) How can I solve this matrix of the first variables ? I could create 3 classes here (CallbackDataUnit, CallbackRow and CallbackSet) but I feel I would be missing real C++ power here. Would it make sense to make callbackRow a single element struct, so that it can be added to callbackSet ?
Thanks for helping
I think you want define new types, not variables.
To do that, you can use typedef or using.
typedef std::vector<callbackDataUnit> callbackRow;
typedef std::vector<callbackRow> callbackSet;
using callbackRow = std::vector<callbackDataUnit>;
using callbackSet = std::vector<callbackRow>;
If you want to just define variables, you can use:
std::vector<callbackDataUnit> callbackRow;
std::vector<decltype(callbackRow)> callbackSet;
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) );
Okay, I have a multi-dimensional array which is statically-allocated. I'd very much like to get a pointer to a portion of it and use that pointer to access the rest of it. Basically, I'd like to be able to do something like this:
#include <stdio.h>
#include <string.h>
#define DIM1 4
#define DIM2 4
#define DIM3 8
#define DIM4 64
static char theArray[DIM1][DIM2][DIM3][DIM4] = {0};
int main()
{
strcpy(theArray[0][0][0], "hello world");
char** ptr = theArray[0][0];
printf("%s\n", ptr[0]);
return 0;
}s
This code results in this error using gcc:
t.c: In function ‘main’:
t.c:17: warning: initialization from incompatible pointer type
char** is apparently not the correct type to use here. I assume it's because statically-allocated arrays are created as a single block in memory while dynamically allocated ones are separated in memory, with each dimension having a pointer to the next one.
However, as you likely noticed, the number of dimensions here is painfully large, and I'm obviously going to need to use actual variables to index the array rather than the nice, slim character 0, so it's going to get painfully long to index the array in actual code. I'd very much like to have a pointer into the array to use so that accessing the array is much less painful. But I can't figure out the correct syntax - if there even is any. So, any help would be appreciated. Thanks.
theArray[0][0] gets rid of the first two dimensions, so you have something of type char [DIM3][DIM4]. The first dimension will drop out when the array decays to a pointer, so the declaration you want is:
char (*ptr)[DIM4] = theArray[0][0];
For what it's worth, gcc also displays a warning for your array declaration: "warning: missing braces around initializer". Static variables and global variables will automatically be initialized to 0, so you can fix the warning by getting rid of the initializer:
static char theArray[DIM1][DIM2][DIM3][DIM4];
Given a declaration
T arr[J][K][L][M];
the following all hold:
Expression Type Decays to
---------- ---- ---------
arr T [J][K][L][M] T (*)[K][L][M]
&arr T (*)[J][K][L][M]
arr[j] T [K][L][M] T (*)[L][M]
&arr[j] T (*)[K][L][M]
arr[j][k] T [L][M] T (*)[M];
&arr[j][k] T (*)[L][M]
arr[j][k][l] T [M] T *
&arr[j][k][l] T (*)[M]
So, in your case, the type of ptr needs to be char (*)[DIM4].
If you are using Visual Studio, a nice way to find out the type of the expression is to use typeid.
cout << typeid(&theArray[0][0]).name();
which prints
char (*)[8][64]
But note that output of typeid().name() is an implementation specific behavior and as such can not be relied upon. But VS happens to be nice in this regards by printing a more meaningful name
Does not matter that it is static, your types don't match
Why a double pointer can't be used as a 2D array?
This is a good example, although the compiler may not complain,
it is wrong to declare: "int **mat" and then use "mat" as a 2D array.
These are two very different data-types and using them you access
different locations in memory. On a good machine (e.g. VAX/VMS) this
mistake aborts the program with a "memory access violation" error.
This mistake is common because it is easy to forget that the decay
convention mustn't be applied recursively (more than once) to the
same array, so a 2D array is NOT equivalent to a double pointer.
A "pointer to pointer of T" can't serve as a "2D array of T".
The 2D array is "equivalent" to a "pointer to row of T", and this
is very different from "pointer to pointer of T".
When a double pointer that points to the first element of an array,
is used with subscript notation "ptr[0][0]", it is fully dereferenced
two times (see rule #5). After two full dereferencings the resulting
object will have an address equal to whatever value was found INSIDE
the first element of the array. Since the first element contains
our data, we would have wild memory accesses.
...
etc....
http://www.ibiblio.org/pub/languages/fortran/append-c.html
Let's say that I want to get the size in bytes or in chars for the name field from:
struct record
{
int id;
TCHAR name [50];
};
sizeof(record.name) does not work.
The solution for this is not so pretty as you may think:
size_in_byte = sizeof(((struct record *) 0)->name)
size_in_chars = _countof(((struct record *) 0)->name)
If you want to use the second one on other platforms than Windows try:
#define _countof(array) (sizeof(array)/sizeof(array[0]))
If you create an instance first, it will work.
record r;
sizeof(r.name);
In C++:
#include <iostream>
using namespace std;;
struct record
{
int id;
char name [50];
};
int main() {
cout << sizeof( record::name) << endl;
}
Edit: A couple of people have pointed out that this is C++0x code, so I guess I must retract my unkind comment regarding VC++. This is not a programming construct I have ever used in my own C++ code, but I have to wonder why sizeof would not work this way in C++03? You hand it a name and it gives you the size. I'd have thought it would take some effort for it not to work. But such is the wonder of the C++ Standard :-)
record is the name of a type, but record.name is not. You somehow have to access name through an instance of the struct. Sorin's answer is the usual C solution:
sizeof ((struct record*)0)->name;
This creates a pseudo-pointer to an instance (or pointer to a pseudo-instance) of struct record, then access the name member, and pass that expression to sizeof. It works because sizeof doesn't attempt to evaluate the pointer expression, it just uses it to compute the size.
You might wanna read this, as it discusses the very same issue and provides all the options mentioned in this thread, and a little more.
struct record
{
static const int kMaxNameChars=50;
int id;
TCHAR name [kMaxNameChars];
};
sizeof(TCHAR)*record::kMaxNameChars //"sizeof(record.name)"
//record::kMaxNameChars sufficient for many purposes.
Portable, perfectly safe and IMO being explicit about raw array length is good practice.
(edit: you might have to macro it in C, if the compiler gets upset about variable array lengths. if you do, consider defining a static const int to the value of the macro anyway!)