2

I wrote a function that calculates all for vertex points for a square given its position with and height. Since one cannot return array's in C I have to do it through a pointer. This is the code I ended up writing:

// Creates a rectangle for mapping a texture. Array must be 20 elements long.
void make_vertex_rect(float x, float y, float w, float h, float *vertex_positions) {
    /*  -1.0,+1.0             +1.0,+1.0
        +----------------------+
        |                      |
        |                      |
        |                      |
        +----------------------+
        -1.0,-1.0             +1.0,-1.0 */
    float new_positions[20] = {
        // We start at the top left and go in clockwise direction.
        //  x,     y,        z,    u,    v
            x,     y,     0.0f, 0.0f, 0.0f,
            x + w, y,     0.0f, 1.0f, 0.0f,
            x + w, y - h, 0.0f, 1.0f, 1.0f,
            x,     y - h, 0.0f, 0.0f, 1.0f
    };
    for (int i = 0; i < 20; ++i) { vertex_positions[i] = new_positions[i]; }
}

Now since C99 provides designated initializers I thought there might be a way to do this without writing a for loop but could not figure it out. Is there a way to do this directly, like:

// Creates a rectangle for mapping a texture. Array must be 20 elements long.
void make_vertex_rect(float x, float y, float w, float h, float *vertex_positions) {
    // Does not compile, but is there a way to get it to compile with a cast or something?
    *vertex_positions = { ... }; 
}
Nils
  • 13,319
  • 19
  • 86
  • 108

4 Answers4

4

Since one cannot return array's in C I have to do it through a pointer

This is sort of true. You can't directly return an array, but you can return a struct that contains an array. Here's a workaround:

struct rect {
    float vertices[4][5];
};

struct rect make_vertex_rect(float x, float y, float w, float h) {
   return (struct rect) {{
       {x,     y,     0.0f, 0.0f, 0.0f},
       {x + w, y,     0.0f, 1.0f, 0.0f},
       {x + w, y - h, 0.0f, 1.0f, 1.0f},
       {x,     y - h, 0.0f, 0.0f, 1.0f}
   }};
}

Obviously you can change the definition of rect to whatever you find most appropriate, this is mostly just to illustrate the point. As long as the array sizes are constant (as they are here), there's no issue.

Jon Reeves
  • 2,426
  • 3
  • 14
2

No, initializers can only be used to initialize objects as they are declared. You can't use them to overwrite an array that already exists.

Either write your for loop, or use memcpy, or just write out the assignments to the destination array elements.

Nate Eldredge
  • 48,811
  • 6
  • 54
  • 82
2

The best you can do here is to either replace the explicit loop with a call to memcpy:

memcpy(vertex_positions, new_positions, sizeof new_positions);

Or to essentially unroll the loop by assigning to each array element manually, i.e.:

int i=0;
vertex_positions[i++] = x;
vertex_positions[i++] = y;
...

Using i for the index here makes it easier to reorder the assignments if you want to change things or made a mistake in the ordering.

dbush
  • 205,898
  • 23
  • 218
  • 273
0

Your method are the simplest. You have to fill 20 elements of vertex_position table which is allocated elsewhere. It can only be done by raw copy elements by elements or by dynamically allocated memory, but this takes longer time.

Wojciech
  • 111
  • 2