Parameter not passing in correctly [duplicate] - c++

This question already has answers here:
When a function has a specific-size array parameter, why is it replaced with a pointer?
(3 answers)
Closed 7 years ago.
I have a function like the following:
void Direct3DRenderer::CreatePrimitive(char *name, Direct3DHelper::VERTEX vertices[])
{
LPDIRECT3DVERTEXBUFFER9 vertex_buf;
d3d_dev->CreateVertexBuffer(4 * sizeof(Direct3DHelper::VERTEX), 0, Direct3DHelper::FVF, D3DPOOL_MANAGED, &vertex_buf, NULL);
VOID *pVoid;
vertex_buf->Lock(0, 0, (void**)&pVoid, 0);
memcpy(pVoid, vertices, sizeof(vertices));
vertex_buf->Unlock();
primitiveMap[name] = vertex_buf;
}
For some reason that sizeof(vertices) is not giving me the right value, or something. This is what I'm inputting:
Direct3DHelper::VERTEX verticesA[] =
{
{ 0, 0, 0, 1, D3DCOLOR_XRGB(255, 0, 0) },
{ 10, 0, 0, 1, D3DCOLOR_XRGB(0, 255, 0) },
{ 0, 10, 0, 1, D3DCOLOR_XRGB(255, 255, 0) },
{ 10, 10, 0, 1, D3DCOLOR_XRGB(0, 0, 255) }
};
If I don't pass it into the function and just replace all the "vertices" with "verticesA," it works... Please help.

The use of the [] syntax does not mean you are passing an array. It's still a pointer, which makes it all the more confusing to use.
So sizeof vertices in your function will be sizeof Direct3DHelper::VERTEX*.
You'll need to pass the size of the array into the function from where it was created. Only in the scope where it was created will the size account for the whole size of the array.
I would actually recommend using something like std::array or std::vector.

Related

Is there a way to overload a constructor with a 2D array (int)?

When I utilize the default constructor, I expect it to call the constructor that accepts an argument; however, this does not occur correctly. When debugging, as far as I can tell it is assigning the values and then the instance simply isn't maintained. I'm not sure if I need to create a helper method instead to pass the object, array, assign out values, and then pass back the object?
My goal is to have a default constructor that passes a hard-coded set of values and then a constructor that accepts the same type of array passed as values.
I've tried passing the array as an argument for the constructors, and while it seems to work for the derived class, it does not work for the base class. I ended up moving the functionality of the overloaded constructor to the default constructor and that works correctly.
This is the base class:
// Puzzle.h
class Puzzle
{
public:
Puzzle();
Puzzle(int grid[gridLength][gridLength]);
~Puzzle();
void Print_Puzzle(); // Displays puzzle in console
protected:
int grid[gridLength][gridLength]; // Our board
private:
};
This is the definition:
Puzzle::Puzzle()
{
int grid[gridLength][gridLength] = // Taken from https://www.puzzles.ca/sudoku_puzzles/sudoku_easy_505.html
{
{ 0, 7, 0, 0, 0, 2, 0, 0, 0 },
{ 0, 9, 0, 3, 7, 0, 0, 0, 0 },
{ 0, 0, 5, 0, 8, 0, 0, 0, 1 },
{ 0, 0, 4, 7, 0, 0, 0, 0, 9 },
{ 0, 0, 0, 0, 9, 6, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 8, 6, 5, 4 },
{ 0, 2, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 1, 0, 4, 3 },
{ 4, 0, 7, 9, 5, 0, 2, 6, 0 }
};
for (int x = 0; x < gridLength; x++)
{
for (int y = 0; y < gridLength; y++)
Puzzle::grid[x][y] = grid[x][y];
}
// Puzzle::Puzzle(grid) // Doesn't work. Not sure how to properly pass the array values.
}
Puzzle::Puzzle(int grid[gridLength][gridLength])
{
for (int row = 0; row < gridLength; row++)
{
for (int col = 0; col < gridLength; col++)
this->grid[row][col] = grid[row][col];
}
}
I expect the default constructor to pass the grid variable and the receiving constructor to assign those values to the instance's member property.
A more convenient way and no less efficient is to use std::array which can be copied, so that you do not have to copy it element-wise:
#include <array>
constexpr int gridLength = 9;
using Grid = std::array<std::array<int, gridLength>, gridLength>;
Grid const grid = {{ // Taken from https://www.puzzles.ca/sudoku_puzzles/sudoku_easy_505.html
{ 0, 7, 0, 0, 0, 2, 0, 0, 0 },
{ 0, 9, 0, 3, 7, 0, 0, 0, 0 },
{ 0, 0, 5, 0, 8, 0, 0, 0, 1 },
{ 0, 0, 4, 7, 0, 0, 0, 0, 9 },
{ 0, 0, 0, 0, 9, 6, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 8, 6, 5, 4 },
{ 0, 2, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 1, 0, 4, 3 },
{ 4, 0, 7, 9, 5, 0, 2, 6, 0 }
}};
class Puzzle {
Grid grid_;
public:
Puzzle(Grid const& grid)
: grid_(grid) // Copy grid into grid_.
{}
};
int main() {
Puzzle p(grid);
}
Alternatively:
class Puzzle {
Grid grid_;
static Grid make_grid() {
Grid grid;
// Your code to fill the grid.
return grid;
}
public:
Puzzle()
: Puzzle(make_grid())
{}
Puzzle(Grid const& grid)
: grid_(grid) // Copy the grid.
{}
};
In my opinion, you are committing a design error.
Never use C arrays in C++, use std::vector or std::array instead.
Try this.
class Sudoku
{
public:
Sudoku(const std::vector<std::vector<int>> initData = { {/* Write your default values here */} })
{
data = initData;
}
private:
std::vector<std::vector<int>> data;
};
if you want to use C-like arrays you will need to understand the only way to pass arrays is via pointers, and is a messy solution.
template <uint32_t width, uint32_t height>
class Sudoku
{
public:
Sudoku(int** initData, int maxX, int maxY)
{
for (int i = 0; i < maxX; i++) {
for (int j = 0; j < maxY; j++) {
data[i][j] = initData[i][j];
}
}
}
private:
std::array<width, std::array<height, int>> data;
};

Comparison of floating point arrays using google test and google mock

I am new to Google's test products and trying them out with some signal processing code. I am trying to assert that to floating point arrays are equal to within some bounds, using google mock as suggested by the answer to this question. I would like to know the recommended method for adding some error tolerance to an expression like the following . . .
EXPECT_THAT( impulse, testing::ElementsAreArray( std::vector<float>({
0, 0, 0, 1, 1, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0
}) ) );
I want the test to pass if the element-wise values in the arrays are within 10-8 of one another.
The following works for me:
using ::testing::Pointwise;
using ::testing::FloatNear;
auto const max_abs_error = 1 / 1024.f;
ASSERT_THAT(
test,
Pointwise(FloatNear(max_abs_error), ref));
Where test and ref are of type std::vector<float>.
One approach is to use the googletest rather than googlemock macros, which results in a more compact assert:
#define EXPECT_FLOATS_NEARLY_EQ(expected, actual, thresh) \
EXPECT_EQ(expected.size(), actual.size()) << "Array sizes differ.";\
for (size_t idx = 0; idx < std::min(expected.size(), actual.size()); ++idx) \
{ \
EXPECT_NEAR(expected[idx], actual[idx], thresh) << "at index: " << idx;\
}
// define expected_array as in the other answer
EXPECT_FLOATS_NEARLY_EQ(impulse, expected_array, 0.001);
Here is one method. First define a matcher outside of the test scope. According to the documentation, the matcher cannot be defined in a class or function . .
MATCHER_P(FloatNearPointwise, tol, "Out of range") {
return (std::get<0>(arg)>std::get<1>(arg)-tol && std::get<0>(arg)<std::get<1>(arg)+tol) ;
}
Then is can be used with Pointwise int the test . . .
std::vector<float> expected_array({
0, 0, 0, 1, 1, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0
});
EXPECT_THAT( impulse, Pointwise( FloatNearPointwise(1e-8), expected_array ) );
But it would be neater if there was a solution that used the builtin FloatNear directly.

Static initializing a struct of unions of arrays

I am trying to write static initializers for this class:
class Cube3x3
{
union CornerData
{
u8 mData8[8];
u32 mData16[4];
u32 mData32[2];
u64 mData64;
};
union EdgeData
{
u8 mData8[12];
u32 mData32[3];
};
CornerData mCorners;
EdgeData mEdges;
static const Cube3x3 sSolved;
};
I've tried this, and a lot of variants, and it seems like nothing I try will work.
const Cube3x3 Cube3x3::sSolved =
{
{ 0, 0, 1, 0, 0, 0, 1, 0 },
{ 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0 }
};
Does anyone know how, or if, its possible to static initialize this?
If you are willing to change Cube3x3 from a class to a struct, you can use:
const Cube3x3 Cube3x3::sSolved = {0};
Update
When a struct is used, you can also initialize the members with non-zero values, like you have in the updated question.
const Cube3x3 Cube3x3::sSolved =
{
{ 0, 0, 1, 0, 0, 0, 1, 0 },
{ 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0 }
};
One solution is to use C++11 lambdas to initialize it.
const Cube3x3 Cube3x3::sSolved = []{
Cube3x3 cube;
std::fill(std::begin(cube.mCorners.mData8), std::end(cube.mCorners.mData8), 0);
std::fill(std::begin(cube.mEdges.mData8), std::end(cube.mEdges.mData8), 0);
return cube;
}();
Live Example
Note the () at the end, which indicates that we are calling that lambda function. If you are using a non-C++11 compiler, or at least one that doesn't yet support C++11 lambdas, you could write a function with basically the same body as you would have when writing a lambda. You then need to call that function when static-initializing the desired object.
Cube3x3 initialize() {
Cube3x3 cube;
std::fill(&cube.mCorners.mData8[0], &cube.mCorners.mData8[8], 0);
std::fill(&cube.mEdges.mData8[0], &cube.mEdges.mData8[8], 0);
return cube;
}
const Cube3x3 Cube3x3::sSolved = initialize();
Live Example
The code is working for me if I add a constructor for your class that takes the CornerData and EdgeData as arguments.
Cube3x3(CornerData cornerData, EdgeData edgeData)
: mCorners(cornerData),
mEdges(edgeData)
{
}
Here is the link: http://ideone.com/XzBXZM

D3D11_INPUT_ELEMENT_DESC: Element types / ordering / packing

Are there concerns (performance or other) related to the types / ordering of elements in a D3D11_INPUT_ELEMENT_DESC structure? For example, I now have an input layout defined like this:
D3D11_INPUT_ELEMENT_DESC QuadInputLayoutDescription[] = {
{ "PRECT", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 0, D3D11_INPUT_PER_INSTANCE_DATA, 1 },
{ "DEPTH", 0, DXGI_FORMAT_R32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_INSTANCE_DATA, 1 },
{ "TEXID", 0, DXGI_FORMAT_R32_UINT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_INSTANCE_DATA, 1 },
{ "SLICE", 0, DXGI_FORMAT_R32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_INSTANCE_DATA, 1 },
{ "UVRCT", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_INSTANCE_DATA, 1 },
{ "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_INSTANCE_DATA, 1 } };
Does it matter that the TEXID element is of type UINT rather than FLOAT here? Is "alignment" against a four component vector struct (float4) preferred; Should I "pack" all the R32G32B32A32_FLOATs together at the beginning of the layout? Is anything padded?
The primary performance issue for input layouts is the total size of them as it directly impacts the amount of data that has to pass through the pre- and post-transform vertex cache. Historically, the idea total size is 32 bytes or 64 bytes.
Otherwise, the types you use don't usually make a lot of difference in terms of performance. The limit on types used is your target hardware Feature Level.

Creating an empty .zip file in C++

I am using a code snippet from this page on how to create a zip file and add and a compress a directory to that zip file. I am running the following on Windows 7 but it does not seem to create the zip file at all.
BSTR bstrFolderOutName = L"C:\\Test\\Archive.zip";
BYTE startBuffer[] = {80, 75, 5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
FILE *f = _wfopen(bstrFolderOutName, L"wb");
fwrite(startBuffer,sizeof(startBuffer),1,f);
fclose(f);
The stated problem, that no file is created, is impossible to answer with the information given. It is most likely due to an invalid file path. However, the OP states in a comment that the path in his example is not the real code.
EDIT: the hex string example that I cited originally was wrong, I just tested.
This code works:
#include <stdio.h>
auto main() -> int
{
FILE* f = fopen("foo.zip", "wb");
//fwrite( "\x80\x75\x05\x06\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 22, 1, f );
fwrite( "\x50\x4B\x05\x06\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 22, 1, f );
fclose(f);
}
Harumph, one cannot even trust Stack Overflow comments. Not to mention accepted answers.
Original text:
Assuming that the OP now has edited the code so that the part below is the real code, then this constant
{80, 75, 5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
is not identical to
"\x80\x75\x05\x06\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
Can the OP spot the relevant difference?
Further, given that, can the OP infer anything about his source of information?
My example from a comment elsewhere.