0

I have got a structure and in it a pointer to a 2D array. But when I try to assign an actual 2D array to that pointer I do not succeed - compiler says that my pointer is a pointer to a 1D array.

Here's my code:

typedef GLfloat Vertex2f[2];
typedef GLfloat TextureCoordinate[2];

typedef struct { 
    GLuint texture_name;  // OpenGL ID of texture used for this sprite 
    Vertex2f *vertices; // array of vertices 
    TextureCoordinate *texture_coords; // texture vertices to match

    GLubyte *vertex_indices;
} game_sprite;

void loadState()
{
    game_sprite ballSprite;

    createAndLoadTexture("ball.png", &ballSprite.texture_name);

    const Vertex2f tempVerticesArray[4] =  {
        {-100.0f, -100.0f},
        {-100.0f, 100.0f},
        {100.0f, 100.0f},
        {100.0f, -100.0f}
    };

    ballSprite.vertices = &tempVerticesArray; //The problem appears to be here
}

How can I make it work?

Thanks.

6 Answers 6

6

You have two problems. First is that tempVerticesArray is const. You can't assign a pointer to a const value (&tempVerticesArray) to a pointer to a non-const variable (ballSprite.vertices) without a typecast, so the compiler is complaining. You should modify the vertices data member to be of the type const Vertex2f *, assuming you're not actually modifying that data ever.

The second problem is that as soon as loadState() ends, the variable tempVerticesArray goes out of scope, and so any dangling pointers to it (specifically ballSprite.vertices) are invalid. You should make tempVerticesArray a static variable so it's not a stack variable that can go out of scope. This is assuming that the ballSprite object is used after that function ends, which I'm guessing it does based on context.

If you do need to modify your vertices after initialization, you'll need to allocate for each ballSprite its own set of vertex data (e.g. using malloc()) and copy the vertex data in (e.g. using memcpy()). If you don't, all ballSprite instances will share a pointer to the same vertex data, and when you modify it, they will all be affected.

Sign up to request clarification or add additional context in comments.

Comments

3

My C is a little rusty, but shouldn't that be:

ballSprite.vertices = tempVerticesArray;

4 Comments

In C/C++ tempVerticesArray has type "Vertex2f*" and &tempVerticesArray has type "Vertex2f[2]*". The first is a pointer to the (first) element, the second is a pointer to an array.
No. Both ballSprite.vertices = tempVerticesArray and ballSprite.vertices = &tempVerticesArray are equivalent. tempVerticesArray has type const Vertex2f[2], and it decays into a pointer to a first element (of type const Vertex2f*). &tempVerticesArray has type const Vertex2f (*)[2], which is a compatible type with const Vertex2f*. The problem is with const correctness.
No, they are not compatible pointer types. One is a pointer to a Vertex2f, the other is a pointer to an array of Vertex2f's.
The types of the expressions are not compatible; remember that Vertext2F is a typedef for GLFloat [2], so the expression ballSprite.vertices is of type GLFloat (*)[2] and the type of the expression &tempVerticesArray is GLFloat (*)[4][2], which are not compatible; the expression tempVerticesArray has type GLFloat [4][2], which will be implicitly converted to GLFloat (*)[2]. EDIT The const issue doesn't help.
3

in C an array is in fact a pointer to the first member, so when you do

ballSprite.vertices = &tempVerticesArray;

you are actually trying to assign to ballSprite.vertices the value of a pointer to a pointer

drop the & and you'll be fine with ballSprite.vertices = tempVerticesArray;

3 Comments

In C++, an array is not a pointer, but decays to one in certain contexts.
@gf: That's true in C as well.
@jamesdlin: ah, wasn't entirely sure.
2

Just to clarify, I don't think

Vertex2f *vertices 

declares a "2D array", it is a 1-dimensionnal array of Vertex2f.

But as pointed by Mitch, the issue is probably that tempVerticesArray, as declared here, is a 1d-array, which is the same as a pointer to a Vertex2f. So &tempVerticesArray is the address of this pointer (a Vertex2f * * ).

Comments

1

You could use either

ballSprite.vertices = tempVerticesArray;

or

ballSprite.vertices = &tempVerticesArray[0];

Comments

1

You might want to allocate memory for the pointer to hold the data. Then memcpy the temporary array to the newly allocated memory. If you're just trying to make the pointer reference the array directly, you might have an issue when you leave that function. The temporary array made on the stack will be freed before you can use the pointer elsewhere.

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.