What is the difference between a structure and a union in C?
A struct gives each member its own storage; a union makes all members share one, so only one holds a value at a time and the size is the largest member's (plus padding).
C#include <stdio.h> struct S { int i; double d; char c; }; union U { int i; double d; char c; }; int main(void) { printf("struct: %zu bytes\n", sizeof(struct S)); printf("union: %zu bytes\n", sizeof(union U)); union U u; u.d = 2.5; printf("u.d = %.1f\n", u.d); return 0; }Here the struct is 24 bytes and the union 8. A union usually pairs with a tag field naming the active member. See unions.
Does member order change the
sizeofof a struct?C#include <stdio.h> struct A { char c; int i; char d; }; struct B { int i; char c; char d; }; int main(void) { printf("%zu %zu\n", sizeof(struct A), sizeof(struct B)); return 0; }It prints
12 8. Eachintis aligned to 4 bytes, soApads 3 bytes aftercand 3 afterd, whileBkeeps the chars together: 4 + 1 + 1 + 2. Padding is implementation-defined (these numbers are GCC on x86-64); order members largest first.Does assigning one struct to another copy it or share it?
C#include <stdio.h> struct Point { int x, y; }; int main(void) { struct Point a = {1, 2}; struct Point b = a; b.x = 9; printf("%d %d\n", a.x, b.x); return 0; }It prints
1 9. Struct assignment copies every member, sobis independent. A pointer member is copied shallowly, though: both structs then share one buffer.What does
typedefdo, and why is it used with structs?typedefcreates an alias for an existing type, not a new type, so you can writePointinstead ofstruct Point.typedef struct Point { int x, y; } Point; typedef int (*Compare)(const void *, const void *); /* names a function pointer type */It helps most with function pointer types.
How do you define a linked list node in C, and why does it need a pointer to itself?
A node holds data and a pointer to the next node. A struct cannot contain itself (its size would be infinite), but it can contain a pointer to itself, since a pointer has a fixed size.
C#include <stdio.h> #include <stdlib.h> typedef struct Node { int value; struct Node *next; /* the typedef name is not defined yet here */ } Node; Node *push(Node *head, int value) { Node *n = malloc(sizeof *n); if (!n) return head; n->value = value; n->next = head; return n; } int main(void) { Node *head = NULL; for (int i = 1; i <= 4; i++) head = push(head, i * 10); for (Node *p = head; p; p = p->next) printf("%d -> ", p->value); printf("NULL\n"); while (head) { Node *next = head->next; free(head); head = next; } return 0; }It prints
40 -> 30 -> 20 -> 10 -> NULL. See the linked list visualizer.Practice it: Reverse Linked List, Middle of the Linked List, Linked List Cycle
Can you compare two structs with
==in C?No.
==is not defined for structs, so it is a compile error; compare member by member.memcmpis wrong in general, because padding bytes have unspecified values and floating point members (0.0and-0.0, NaN) need their own rules.What value does
Cget inenum { A, B = 5, C }?C#include <stdio.h> enum Level { A, B = 5, C }; int main(void) { printf("%d %d %d\n", A, B, C); return 0; }It prints
0 5 6. Enumerators start at 0 and each is one more than the previous unless given a value, soCfollowsB = 5. In C an enumerator is anintconstant (C23 also allows wider ones), and the compiler does not stop an enum variable from holding other values.What is a flexible array member?
A flexible array member (C99) is a size-less array as the last member of a struct, so one
mallocholds the struct and its data together.C#include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct { size_t len; char data[]; /* flexible array member, must be last */ } Buffer; int main(void) { const char *text = "packet payload"; size_t n = strlen(text) + 1; Buffer *b = malloc(sizeof *b + n); if (!b) return 1; b->len = n - 1; memcpy(b->data, text, n); printf("%zu: %s\n", b->len, b->data); free(b); return 0; }It prints
14: packet payload;sizeof(Buffer)excludes the array. The oldchar data[1]trick is undefined behavior past element 0.What are bit fields in C, and when should you avoid them?
A bit field gives a struct member an exact width in bits, so several small values share one word. They are used for hardware registers and compact sets of flags.
C#include <stdio.h> struct Flags { unsigned int ready : 1; /* 0 or 1 */ unsigned int mode : 3; /* 0 to 7 */ unsigned int level : 4; /* 0 to 15 */ }; int main(void) { struct Flags f = {1, 7, 12}; printf("%d %d %d\n", f.ready, f.mode, f.level); f.mode++; /* 8 does not fit in 3 bits: wraps to 0 */ printf("%d\n", f.mode); return 0; }It prints
1 7 12, then0: an unsigned bit field wraps modulo its width. You cannot take a bit field's address (&f.modedoes not compile), and bit order and padding are implementation-defined, so for a file or network format use shifts and masks instead.What is the difference between
.and->, and should you pass a struct by value or by pointer?.accesses a member of a struct and->a member through a pointer to a struct:p->xmeans(*p).x. The parentheses are needed because.binds tighter than*.C#include <stdio.h> struct Point { int x, y; }; void move_copy(struct Point p) { p.x += 10; } /* changes a copy */ void move_ptr(struct Point *p) { p->x += 10; } /* p->x is (*p).x */ int main(void) { struct Point pt = {1, 2}; move_copy(pt); printf("after move_copy: %d\n", pt.x); move_ptr(&pt); printf("after move_ptr: %d\n", pt.x); return 0; }It prints
1, then11: a struct passed by value is copied, so only the pointer version changes the caller's struct. Pass large structs by pointer (const struct Point *when the function only reads) to avoid the copy. See structs and pointers.
C Structures and Unions Interview Questions
Structs, unions, padding and the self-referential structs linked lists are made of.
10 questions