user2635088 user2635088 - 1 month ago 13
C Question

Declaring a struct on the stack

This is from Zed Shaw's Learn C the Hard Way:

#define MAX_DATA 15
#define MAX_ROWS 100


struct Address {
int id;
int set;
char name[MAX_DATA];
char email[MAX_DATA];
};

struct Database {
struct Address rows[MAX_ROWS];
};

struct Connection {
FILE *file;
struct Database *db;
};


void Database_create(struct Connection *conn)
{
int i = 0;

for (i = 0; i < MAX_ROWS; i++) {

struct Address addr = {.id = i, .set = 0};

conn->db->rows[i] = addr;
}
}


For the line
struct Address addr = {.id = i, .set = 0}
, we're declaring addr on the stack, and we're assigning that struct to
conn->db->rows[i]
. Before calling database_create(), I've initialized
conn->db = malloc(sizeof(struct Database));


Once the function exits, addr gets cleaned up since it was on the stack. How does the value of
addr
persist inside
conn->db->rows[i]
? Is the assignment creating a copy of the data stored in
addr
and storing it on the heap location of
conn->db->rows[i]
?

Thanks!

Answer

Yes, this is a copy assignment.

In this case, you have an array of structures, which size equals to MAX_ROWS*sizeof(struct Address). So, there is plenty of space in it anyway.

Consider the following:

struct coord{int x,y;};
struct coord a = {0,0};
struct coord b;
b = a; //This is a copy assignment

Here, each row of the array holds a complete structure, and you copy the value of addr inside.


What would not be a copy assignment would be an array of pointers:

struct Database {
    struct Address *rows[MAX_ROWS];
};

And after, conn->db->rows[i] = &addr;

Obviously, you would run into problems in this situation, as the values referenced by the pointers are undefined, and the different rows are highly likely to contain the same address. But this would be fine if you were using dynamic allocation.

You could try to display sizeof(*(conn->db)) or sizeof(conn->db->rows) in both cases, if you want to see the fact that the array really holds MAX_ROWS structures when not using pointers.