简体   繁体   中英

How to deal with structs in c?

i was following a tutorial on how to make a simple sqlite clone in c and the tutorial mentioned building a struct called Row and it's defined below:

typedef struct 
{
int id;
char name[COLUMN_USERNAME_SIZE];
char email[COLUMN_EMAIL_SIZE];
}Row;

and it was defined a preprocessor macro to get the size of a member of that struct but i can't understand its definition. it's defined below:

#define size_of_attribute(Struct, Attribute) sizeof(((Struct*)0)->Attribute) 

so, what does the tutorial mean here by using a name of a struct not an object of it and why use the * operator and most importantly, what does 0 mean here?

You can use sizeof in two ways: Either with a data type or with a data object.

Given a variable like this you can use both versions:

Row oneRow;

size_t size1 = sizeof (Row);
size_t size2 = sizeof (oneRow);

If you want to get the size of a specific field inside a type you can only use second variant where you need an object.

size_t size3 = sizeof (oneRow.name);

Row *pRow = &oneRow;
size_t size4 = sizeof (pRow->name);

Here is where the macro comes in. It avoids the need to provide an existing data object.

sizeof(((Struct*)0)->Attribute) 

This takes address 0 and interpretes it as a pointer to Struct . This is similar to my last example. Then it specify the field to get to the object we want the size from.

If you use it with your type this is what you get:

size_t size = size_of_attribute(Row, name);

After processing is done by preprocessor you get this:

size_t size = sizeof(((Row*)0)->name);

This is similar to

Row *pRow = NULL;
size_t size = sizeof(pRow->name;

Note: This looks like dereferencing a NULL pointer, but it doesn't. sizeof does not access the data object but only evaluates to its size. No read access is done here.

When invoked as

size_of_attribute( Row, id );

that macro is expanded to

sizeof(((Row *)0)->id);

What it's doing is casting the value 0 as a pointer to Row , then using the member selection operator to pick the id member, and evaluating the size of that member.

Except in the case of variable-length array expressions, sizeof does not evaluate its operand - it doesn't matter that 0 is an invalid address, all that matters id the type of the expression. If you have a pointer to Row p , the the type of the expression p->id is int , regardless of whether p is currently pointing to an instance of Row or not.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM