0

I have a 2D array organized as

float vertices[3][3]

In one iterative loop of my program, I see in my debugger that the the array fills up as so:

vertices[0] = {-1, -1, 1}
vertices[1] = {-1, -.5, .5}
vertices[2] = {-.5, -1, .5}

I then pass the three vertices to my triangle class.

Triangle *t = new Triangle(vertices[0], vertices[1], vertices[2]);
triangles.push_back(*t);

The triangle constructor is coded as so:

Triangle::Triangle(float *a, float *b, float *c)
{
    memcpy(v1, a, sizeof(a));
    memcpy(v2, b, sizeof(b));
    memcpy(v3, c, sizeof(c));
}

My debugger now shows

v1 = {-1, -431602080, -431602080}
v2 = {-1, -431602080, -431602080}
v3 = {-.5, -431602080, -431602080}

Debugger also shows that a/b/c are only 1 element long? So apparently only the first element of the array is being passed?

1
  • 1
    You also need to pass the size of arrays! Commented Sep 15, 2015 at 5:21

5 Answers 5

3

sizeof(a)

is actually

sizeof (float*)

which is not 3x float, it is 1 pointer. Pass additional parameter size_t number_of_members_in_array and replace

memcpy(v1, a, sizeof(a));

with

memcpy(v1, a, sizeof(*a) * number_of_members_in_array);

Triangle::Triangle(float *a, int numA, float *b, int numB, float *c, int numC)
{
    memcpy(v1, a, sizeof(float) * numA);
    memcpy(v2, b, sizeof(float) * numB);
    memcpy(v3, c, sizeof(float) * numC);
}
Sign up to request clarification or add additional context in comments.

3 Comments

This approach (or using a std::vector) will also help you later on to convert your vertices to the quite popular 4 element version: <x,y,z,w> where w = 0: Point and w=1 : Vector.
Interesting thing is if you write in code smth like "float a[3];", than sizeof(a) would be 3*sizeof(float), though it doesn't affect your question
It is the signature (types of arguments) of the function. He still could write it with `` float[3] a`` instead of float*a. Even though noone ever does that and I even forgot why this is usually avoided, having avoided that myself since eternity.
0

The problem here is your use of the sizeof operator, because once an array has decayed to a pointer it looses all size information, and in the function doing e.g. sizeof(a) will only give you the size of the pointer and not what it points to.

There's an easy way to solve these problems in C++, and that is to use either std::vector or std::array instead. If you for some reason don't want to use those handy classes, then you need to pass the size to the function in some way, like for example an argument or as a template parameter.

Comments

0

In your case, sizeof(a) will give you the size of the pointer, not the data it points to. This is because a is a float pointer!

Do this: Pass number of elements (3 in your case) as a parameter:

    Triangle::Triangle(float *a, float *b, float *c, int numElements)
    {
        memcpy(v1, a, sizeof(a) * numElements);
        memcpy(v2, b, sizeof(b) * numElements);
        memcpy(v3, c, sizeof(c) * numElements);
    }

Comments

0

An alternative is to expected fixed size float array:

Triangle::Triangle(const float (&a)[3], const float (&b)[3], const float (&c)[3])

but passing size or using std::array<float, 3> or std::vector<float> seems simpler.

Comments

0

Aside from the other solutions, I want to point out that your code has a memory leak:

Triangle *t = new Triangle(vertices[0], vertices[1], vertices[2]);
triangles.push_back(*t);

When you push_back(*t), you are pushing a copy of the allocated object at *t, not a copy of the pointer t. The vector internally allocates space for another Triangle and copies the given object into it. After this code, that pointer is lost and the allocated object is orphaned/leaked.

If you mean to keep your triangles as individually-allocated objects, then triangles should be a vector<Triangle *> and the code should look like this:

Triangle *t = new Triangle(vertices[0], vertices[1], vertices[2]);
triangles.push_back(t);

If you mean to keep triangles as a vector<Triangle>, then you want something more like this:

Triangle t(vertices[0], vertices[1], vertices[2]);
triangles.push_back(t);

Or, if your compiler/stl implementation supports vector::emplace_back(), this is even simpler:

triangles.emplace_back(vertices[0], vertices[1], vertices[2]);

Which does the construction directly into the new entry in the vector.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.