can not count array elements after passing as argument - c++

I am having issues counting the array elements after passing it into an arguement
void GXDX::LoadMesh(GXVector vertices[], UINT indices[] = NULL)
{
D3D10_BUFFER_DESC bufferDesc;
UINT numVerts = sizeof(vertices)/sizeof(GXVector);
bufferDesc.Usage = D3D10_USAGE_DEFAULT;
bufferDesc.ByteWidth = sizeof(GXVector) * numVerts;
bufferDesc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
bufferDesc.MiscFlags = 0;
bufferDesc.CPUAccessFlags = 0;
code..............
}
In the following line above
UINT numVerts = sizeof(vertices)/sizeof(GXVector);
I am trying to count the number of elements in the array varible vertices. But I am not getting an accurate count, if not one at all.
When I did a step through, I notice that I am not able to see all the values in the array, only the first value of the array.
So I am not sure if I am passing the array correctly as an arguement. In another application, I did the same thing and i was able to see all the values in the step through. I pass the array like this.
GXVector vertices[] = { {D3DXVECTOR3(0.5f, 0.5f, 0.5f)},
{D3DXVECTOR3(0.5f, -0.5f, 0.5f)},
{D3DXVECTOR3(-0.5f, -0.5f, 0.5f)},
{D3DXVECTOR3(-0.5f, -0.5f, 0.5f)},
{D3DXVECTOR3(-0.5f, 0.5f, 0.5f)},
{D3DXVECTOR3(0.5f, 0.5f, 0.5f)},
};
UINT indices[] = {0,1,2,3,4};
GXRenderManager::Device()->LoadMesh(vertices, indices);
So in a nutshell, Am I passing the array right as an arguement, what am I doing wrong where I can not get the correct element count of the array.

Yes, you are passing the array correctly; however, in C (and C++), arrays don't contain their size. So you need to pass the size of the array as a separate parameter. Arrays effectively decay into pointers when passed as a parameter into a function, so sizeof(vertices) will give you the size of the pointer type, not the size of the array. You can walk through the array though, either with pointer arithmetic or indexing - but you need to know its exact size, otherwise you can get out of bounds.
This is one main reason why in C++ std::vector is recommended to use instead of raw arrays.

You are passing the array correctly. Array parameters simply do not remember their lengths. Instead, they're passed as though they were mere pointers, so your sizeof expression is getting the size of a pointer, not the size of the entire array that the pointer points at.
If the function needs to know the lengths of the arrays, then you need to pass the lengths as additional parameters.

C arrays (which is what you're passing) don't pass the size (length) along unless you explicitly specify the array length in the function declaration. The typical way to solve this in C is to pass the array length into the function as well as the array.
In C++ much better is to use a std::vector and pass it around. It already knows its own size and the problem vanishes compeltely.

The sizeof(vertices) operation that you are doing is not a runtime operation, it is actually resolved by the compiler. So, as long as the declaration of the array is in scope, you will get a correct result.
That is not so in a function, because you could be passing arrays from several other points in the code, hence the incorrect result. (And hence the confusion for the debugger as well).

Arrays decay into pointers when you pass them like that. What kind of sense did you think that UINT indices[] = NULL made?
You can pass the length around with the array, like you would have in C, or you could use some more intelligent construct like a vector or boost::array.

The C sizeof operator is evaluated at compile-time, not run-time. As written, the compiler does not have enough information to determine the size of the array.
Instead, change your function prototype. Pass in a pointer to the array as well as the length of the array.

Related

Accessing an Element from an int ** array in C++

I am creating a 2D-Array in C++ and need to pass this array as a parameter in a function. In my function, I need to access an element from the array in order to save it as a value, i.e.:
int lowestPoint(int **arr, int x, int y, int n) {
minVal = *(*(arr+x)+y); // here is where I'm getting the exception
return minVal;
}
I've tried setting minVal to arr[X][Y] and have tried to pass the array in as other variations instead of just **arr but nothing seems to be working.
The array is initialized in my main function as int arr[x][y] and I pass it into another function by casting it as otherFunc(reinterpret_cast<int **>((*arr)[n]), n), and then from that function, send it to lowestPoint by calling int val = lowestPoint(arr,i,j,n). I think these calls could be problematic but I'm uncertain how to fix it - I really have no experience with 2D arrays in C++ and it's soo much simpler in Java. I keep getting an EXC_BAD_ACCESS error for the array, so if anyone has any idea how to fix that, I'd really appreciate it. Thanks!
EDIT:
"n" is the size of the array; for example if it's a 3x3 array, n = 3. I just initialized the array as int arr[n][n] and then stored elements. I know the actual array itself represents the correct value, it just can't access it once I send it to another function.
When you pass the array to the first function using reinterpret_cast((*arr)[n]), instead of passing the pointer to the actual array, you are passing the value in location [0][n] (by using (*arr)[n]) and casting it to **arr. So in essence you get a new array that points to a random location in memory that is equal to the content of that array slot.
I am not sure what you intended to do, but if you wanted to pass the actual array, just pass arr. If you planned to pass a sub-array, this method is incorrect altogether as you pass an offset inside an array and you will get skewed data.
Hope This helps,
Lior

How to pass dynamic and static 2d arrays as void pointer?

for a project using Tensorflow's C API I have to pass a void pointer (void*) to a method of Tensorflow. In the examples the void* points to a 2d array, which also worked for me. However now I have array dimensions which do not allow me to use the stack, which is why I have to use a dynamic array or a vector.
I managed to create a dynamic array with the same entries like this:
float** normalizedInputs;//
normalizedInputs = new float* [noCellsPatches];
for(int i = 0; i < noCellsPatches; ++i)
{
normalizedInputs[i] = new float[no_input_sizes];
}
for(int i=0;i<noCellsPatches;i++)
{
for(int j=0;j<no_input_sizes;j++)
{
normalizedInputs[i][j]=inVals.at(no_input_sizes*i+j);
////
////
//normalizedInputs[i][j]=(inVals.at(no_input_sizes*i+j)-inputMeanValues.at(j))/inputVarValues.at(j);
}
}
The function call needing the void* looks like this:
TF_Tensor* input_value = TF_NewTensor(TF_FLOAT,in_dims_arr,2,normalizedInputs,num_bytes_in,&Deallocator, 0);
In argument 4 you see the "normalizedInputs" array. When I run my program now, the calculated results are totally wrong. When I go back to the static array they are right again. What do I have to change?
Greets and thanks in advance!
Edit: I also noted that the TF_Tensor* input_value holds totally different values for both cases (for dynamic it has many 0 and nan entries). Is there a way to solve this by using a std::vector<std::vector<float>>?
Respectively: is there any valid way pass a consecutive dynamic 2d data structure to a function as void*?
In argument 4 you see the "normalizedInputs" array. When I run my program now, the calculated results are totally wrong.
The reason this doesn't work is because you are passing the pointers array as data. In this case you would have to use normalizedInputs[0] or the equivalent more explicit expression &normalizedInputs[0][0]. However there is another bigger problem with this code.
Since you are using new inside a loop you won't have contiguous data which TF_NewTensor expects. There are several solutions to this.
If you really need a 2d-array you can get away with two allocations. One for the pointers and one for the data. Then set the pointers into the data array appropriately.
float **normalizedInputs = new float* [noCellsPatches]; // allocate pointers
normalizedInputs[0] = new float [noCellsPatches*no_input_sizes]; // allocate data
// set pointers
for (int i = 1; i < noCellsPatches; ++i) {
normalizedInputs[i] = &normalizedInputs[i-1][no_input_sizes];
}
Then you can use normalizedInputs[i][j] as normal in C++ and the normalizedInputs[0] or &normalizedInputs[0][0] expression for your TF_NewTensor call.
Here is a mechanically simpler solution, just use a flat 1d array.
float * normalizedInputs = new float [noCellsPatches*no_input_sizes];
You access the i,j-th element by normalizedInputs[i*no_input_sizes+j] and you can use it directly in the TF_NewTensor call without worrying about any addresses.
C++ standard does its best to prevent programmers to use raw arrays, specifically multi-dimensional ones.
From your comment, your statically declared array is declared as:
float normalizedInputs[noCellsPatches][no_input_sizes];
If noCellsPatches and no_input_sizes are both compile time constants you have a correct program declaring a true 2D array. If they are not constants, you are declaring a 2D Variable Length Array... which does not exist in C++ standard. Fortunately, gcc allow it as an extension, but not MSVC nor clang.
If you want to declare a dynamic 2D array with non constant rows and columns, and use gcc, you can do that:
int (*arr0)[cols] = (int (*) [cols]) new int [rows*cols];
(the naive int (*arr0)[cols] = new int [rows][cols]; was rejected by my gcc 5.4.0)
It is definitely not correct C++ but is accepted by gcc and does what is expected.
The trick is that we all know that the size of an array of size n in n times the size of one element. A 2D array of rows rows of columnscolumns if then rows times the size of one row, which is columns when measured in underlying elements (here int). So we ask gcc to allocate a 1D array of the size of the 2D array and take enough liberalities with the strict aliasing rule to process it as the 2D array we wanted. As previously said, it violates the strict aliasing rule and use VLA in C++, but gcc accepts it.

Misunderstanding of C++ array structure

I'm new to C++ and I learned with different tutorials, in one of them I found an example of code:
I have pointed by numbers of lines, that I completely do not understand;
Does this array in array or something like that?
I can understand the second call, but what is the first doing? There is already
"coordinates[blocks[num]]", aren't there? Why need again blocks(i) ?
How do you make this part of the code easier? Did struct with this arrays
don't make easier getting value from arrays?
Thanks in advance!
// Global vars
Struct Rect {
float left;
}
Rectangle *coordinates;
int *blocks;
coordinates = new Rect[25];
blocks = new int[25];
// in method storing values
const int currentBlock = 0; //var in cycle
coordinates[currentBlock].left = column;
blocks[currentBlock] = currentBlock;
//get element method
const Rect& classA::Coords(int num) const
{
return coordinates[blocks[num]]; //(2)
}
//and calling this method like
Coords(blocks[i]); //(3)
Coords(i); //(3)
// (4)
No, not really. Lots of people will think of them as arrays and even describe them as arrays, but they're actually not. coordinates and blocks are both pointers. They just store a single address of a Rect and an int respectively.
However, when you do coordinates = new Rect[25];, for example, you are allocating an array of 25 Rects and setting the pointer coordinates to point at the first element in that array. So, while coordinates itself is a pointer, it's pointing at the first element in an array.
You can index coordinates and blocks like you would an array. For example, coordinates[3] will access the 4th element of the array of Rects you allocated. The reason why this behaves the same as arrays is because it actually is the same. When you have an actual array arr, for example, and you do arr[4], the array first gets converted to a pointer to its first element and then the indexing occurs.
No, this is not an array of arrays. What it is doing is looking up a value in one array (blocks[num]) and using that to index the next array (coordinates[blocks[num]]). So one array is storing indices into the other array.
I'll ignore that this won't compile, but in both cases you are passing an int to the Coords function. The first case looks incorrect, but might not be. It is taking the value at blocks[i], passing that to the function then using that value to index blocks to get another value, then using that other value to index coordinates. In the second case, you are just passing i, which is being used to index blocks to give you a value with which you index coordinates.
That's a broad question that I don't think I can answer without knowing exactly what you want to simplify and without seeing some real valid code.

C++ conversion from array to pointer

I am bit struggling with kinda easy task. I need to convert array to pointer.
GLfloat serieLine[8][80];
GLfloat *points = &serieLine[0][0];
this gives me just first value, but how can I get all values in the array?
If you want pointer to an array, you can do it like this:
GLfloat (*points)[80] = serieLine;
points will point to the first row of serieLine. If you increment points, it will point to the next row.
Increment the pointer, and it'll point at the next value in the array (so once you've incremented it 8*80 times you'll have seen all of the values)

Declaring char[][512]?

I have an C++ SDK that requires a char[][512] as a parameter. I know that this is supposed to be a list of file names and the number of files could vary. For the life of me I cannot figure out how to declare this. I have an array of CStrings and I am trying to copy them over using strcpy_s and then pass them into the SDK. Any idea on how to do this?
This declaration has a special meaning when used to declare parameter of a function. Within the parameter list it is equivalent to char[100][512], char[123][512], char[3][512] (you get the idea - the first size can be just anything, it is simply ignored) and also to char (*)[512]. Effectively, it will accept as an argument a 2D array of chars with flexible (arbitrary) first size.
The array that you will actually pass to this function should be declared with a concrete first size, for example
char names[3][512] = { "abc", "cde", "fgh" };
if you know the first size at compile time, of course.
If the first size is only known at run time (say, n), you'll have to allocate the array dynamically
char (*names)[512] = new char[n][512];
// Now fill it with names
or, more elegantly, with a typedef
typedef char TName[512];
TName* names = new TName[n];
// Now fill it with names
I expect that the SDK function you are talking about also asks you to pass the first size of the name array as another parameter.
It means 2D array of char. The number of rows could vary, and it should/may be specified in another parameter. C/C++ compilers need to know the number columns when a 2D arrays is passed ,So they can build the mapping function. Simply because arrays decay to pointers when they are passed as parameters, size information is lost. For example:
void fun(char matrix[][512], int rows);
...
char matrix[100][512];
...
fun(matrix, 100);
The mapping function that the compiler construct for a 2D array is similar to:
// arrays in C/C++ are stored in Row-Major Order
matrix[i][j] == matrix[i*numberOfColumns + j]
As you can see, when a 2D array is passed and the size information is lost, we need only the number of columns to index any element in this array.
Here is a way to convert an argv-style array of filenames into the form your SDK needs.
typedef char Char512[512];
Char512 * convert(const char *names[], int n)
{
Char512 * arr;
arr = new char[n][512];
for (int i = 0; i < n; n++)
::strncpy(arr[i], names[i], 512);
return arr;
}
When in doubt, use a typedef.
Just a reminder, if you new[] something, you must delete[] (not delete) it sometime.