Live data from Hacker News

Structures in C: From Basics to Memory Alignment

abstractexpr.com

31–40 of 58 posts

Re: Structures in C: From Basics to Memory Alignment

#31

> The only good reason to use packed structures is when you need to map some memory (e.g. hardware registers exposed to memory) bit by bit to a structure. Another common reason is when two CPUs of different architecture need to access the same structure in memory. E.g. you have a RiscV and an Arm64 processor in the same system, sharing memory. Or you read structured binary data from disk and need to specify an exact…

Whoa, I didn’t know there were systems where two different CPUs shared memory… How does that work? Any examples I might recognize of such systems?

Re: Structures in C: From Basics to Memory Alignment

#32

Good article, a couple nits/additional notes: 1. The article points out you should compare structs field by field, but it doesn't explain why memcmp wouldn't work. The reason is that the padding between the fields might not necessarily be zeroed in all cases. Field by field comparison is resilient to this. 2. The article proposes this for dynamic allocation: struct Vector2D *vec = malloc(sizeof(struct Vector2D)); I t…

I’ve been wondering about (1) recently—is there a way to memset the entire stack frame at the start of a function such that memcmp works as expected? Also, what are the performance implications of comparing a padded struct member-by-member vs a single big memcmp? Is member-by-member faster because you’re comparing less in total, or is memcmp faster because it’s one big contiguous compare? Or is it more complicated? R…

(1) If the pointers you pass to memcmp are know to the compiler, then memcmp will be treated as an intrinsic, and generally the compiler generates the optimal set of instructions for a given struct.

(2) Correct. The expression is only evaluated at compile time.

Re: Structures in C: From Basics to Memory Alignment

#33
> The memory is uninitialized so it is a good idea to initialize it to zero bytes. We can do this by calling the memset function with the pointer to our new struct, the initialization value 0, and the size of our structure:

Or just calloc(), which also takes a count and an element size, convenient when you're allocating arrays.

Re: Structures in C: From Basics to Memory Alignment

#34
> One might assume that the compiler puts all its members directly behind each other in memory with no gaps in between and that the size of each structure is exactly the same as the sum of the sizes of all of its members. Such a structure is called a packed structure:

> This is NOT how a compiler usually lays out a structure in memory.

Just explain how it works instead of assuming that the reader is making an (incorrect) assumption. I think you're caught making that assumption because you've introduced the topics in a non-optimal order.

I would split up "Element Order and Addressing" and remove the picture there because it's misleading. You can talk about addressing without explaining how the struct is laid out in memory. You don't even need structs to explain addressing ("& takes the address of an object"). Then, once you've introduced basic addressing and struct alignment/padding, you could introduce addressing of struct fields. But I suspect it won't have much value at that point because the logistics will be a natural consequence of the earlier topics.

Re: Structures in C: From Basics to Memory Alignment

#35
post #15

I'll try not to be too pedantic. > If we declare a structure variable without initializing it, like any other variable in C, it will be uninitialized at first and may contain random values. Really, it's important to stress that as far as you are concerned, uninitialized things don't contain values, they only contain undefined behavior. > But in complex programs, a structure can easily have 20 members and more. Mostly…

Why would you heap allocate the struct? You will just have to heap allocate again for the actual data structure.

Re: Structures in C: From Basics to Memory Alignment

#36
> But what if we want a struct to feel like a real C type?

Remove this; it's already a real type. You could go over the two namespaces and why you need to type 'struct' otherwise, but I wouldn't present a false dichotomy of real and "unreal" types.

> Declaring a Struct as a New Type

It's not really a new type. It's a type alias, and the two names can be used interchangeably. I would just call it a type alias.

https://en.cppreference.com/w/c/language/typedef

> If we declare a structure variable without initializing it, like any other variable in C, it will be uninitialized at first and may contain random values.

I also see no mention of = {} or = {0} (I forget which is Standard C and which is C++). Since you already talk about "random values", you might as well explain how to 0-initialize a struct.

Re: Structures in C: From Basics to Memory Alignment

#37
post #19

> The only good reason to use packed structures is when you need to map some memory (e.g. hardware registers exposed to memory) bit by bit to a structure. Another common reason is when two CPUs of different architecture need to access the same structure in memory. E.g. you have a RiscV and an Arm64 processor in the same system, sharing memory. Or you read structured binary data from disk and need to specify an exact…

"The only good reason to " The word opinionated was coined and adopted in English to describe a certain attitude. It has functioned fine for (probably) centuries (who knows, and I can't be bothered to research too far). Then came the age of IT and blow me, are we not opinionated to the point of ridiculousness. A sentence construction along the lines of "The only good reason to" [do x] "is" [y], seems to invite a nega…

Good call. Such statement implies that there is no other reason, as obvious as that might sound. Just say "One reason to" to avoid implying that's the only one.

> I'm pretty sure packed structures have other uses.

Like reducing memory footprint.

Re: Structures in C: From Basics to Memory Alignment

#38
post #33

> The memory is uninitialized so it is a good idea to initialize it to zero bytes. We can do this by calling the memset function with the pointer to our new struct, the initialization value 0, and the size of our structure: Or just calloc(), which also takes a count and an element size, convenient when you're allocating arrays.

I thought the same thing. Why is calloc not widely used?

That said, when initializing structs `= { 0 }` can be used to set all members 0. And at least in more recent compilers you can used the designated initializer with dynamic allocation by casting:

    Foo* f = malloc(sizeof(Foo));
    *f = (Foo) { .bar = 1, .baz = “car” };
If a member is missed, it will be set to zero (the value for uninitialized static storage).

Re: Structures in C: From Basics to Memory Alignment

#40
post #36

> But what if we want a struct to feel like a real C type? Remove this; it's already a real type. You could go over the two namespaces and why you need to type 'struct' otherwise, but I wouldn't present a false dichotomy of real and "unreal" types. > Declaring a Struct as a New Type It's not really a new type. It's a type alias, and the two names can be used interchangeably. I would just call it a type alias. https:/…

{0} is standard C. {} is currently a (common) compiler extension but will be standard C23: https://open-std.org/JTC1/SC22/WG14/www/docs/n2900.htm
Post reply on HN