Programming Language & Its Applications — Pointers, Structure and Data Files in C, NEC licence examination syllabus (Nepal Engineering Council).
A struct gives every member its own space; a union makes them all share one. The size difference tells the whole story.
A struct groups related values of different types into one named object — a student record, a point, a date. A union looks identical in syntax but lays all members at the same address, so only one is valid at a time. Structs are what you use ninety-nine percent of the time; unions matter for memory-constrained code, type-punning and tagged variants.
fread. This is also where padding becomes urgent: get it wrong and your struct no longer matches the file, so you read garbage. Search "__attribute__((packed)) network header" to see how systems programmers force the layout to match the wire format exactly.#include <stdio.h>
#include <string.h>
typedef struct {
int roll;
char name[30];
float marks[3];
float total;
} Student;
int main(void) {
Student s = {101, "Ram Bahadur", {78.0f, 85.5f, 91.0f}, 0};
s.total = 0;
for (int i = 0; i < 3; i++) s.total += s.marks[i];
printf("Roll : %d\n", s.roll);
printf("Name : %s\n", s.name);
printf("Marks: %.1f %.1f %.1f\n",
s.marks[0], s.marks[1], s.marks[2]);
printf("Total: %.1f Avg: %.2f\n", s.total, s.total/3);
/* via a pointer */
Student *p = &s;
printf("through pointer: %s scored %.1f\n",
p->name, p->total);
/* struct assignment copies EVERYTHING, member by
member - including the whole name array */
Student t = s;
strcpy(t.name, "Sita Devi");
printf("s.name=%s t.name=%s\n", s.name, t.name);
return 0;
}
Output:
Roll : 101
Name : Ram Bahadur
Marks: 78.0 85.5 91.0
Total: 254.5 Avg: 84.83
through pointer: Ram Bahadur scored 254.5
s.name=Ram Bahadur t.name=Sita Devi
Notice that Student t = s; performs a full member-wise copy — unlike arrays, structs are assignable. But it is a shallow copy: if a member were a pointer, both structs would point to the same memory.
#include <stdio.h>
#include <string.h>
struct S { int i; float f; char s[8]; };
union U { int i; float f; char s[8]; };
int main(void) {
printf("sizeof(struct S) = %zu\n", sizeof(struct S));
printf("sizeof(union U) = %zu\n", sizeof(union U));
union U u;
u.i = 65;
printf("wrote i=65 -> i=%d s[0]='%c'\n", u.i, u.s[0]);
u.f = 3.14f; /* CLOBBERS i */
printf("wrote f -> f=%.2f i=%d (garbage)\n",
u.f, u.i);
strcpy(u.s, "HELLO");
printf("wrote s -> s=%s f=%g (garbage)\n",
u.s, u.f);
/* all members share the address */
printf("&u.i=%p &u.f=%p &u.s=%p\n",
(void*)&u.i, (void*)&u.f, (void*)u.s);
return 0;
}
Output:
sizeof(struct S) = 16
sizeof(union U) = 8
wrote i=65 -> i=65 s[0]='A' <-- 65 is ASCII 'A'
wrote f -> f=3.14 i=1078523331 (garbage)
wrote s -> s=HELLO f=1.14314e+27 (garbage)
&u.i=0x7ffd4a1b2c30 &u.f=0x7ffd4a1b2c30 &u.s=0x7ffd4a1b2c30
#include <stdio.h>
#include <stddef.h>
struct Bad { char c; int i; char d; }; /* 12 */
struct Good { int i; char c; char d; }; /* 8 */
int main(void) {
printf("Bad = %zu bytes\n", sizeof(struct Bad));
printf("Good = %zu bytes\n", sizeof(struct Good));
printf("Bad offsets: c=%zu i=%zu d=%zu\n",
offsetof(struct Bad,c), offsetof(struct Bad,i),
offsetof(struct Bad,d));
printf("Good offsets: i=%zu c=%zu d=%zu\n",
offsetof(struct Good,i), offsetof(struct Good,c),
offsetof(struct Good,d));
return 0;
}
Output:
Bad = 12 bytes
Good = 8 bytes
Bad offsets: c=0 i=4 d=8
Good offsets: i=0 c=4 d=5
#include <stdio.h>
#include <string.h>
/* The safe, standard way to use a union: pair it with a
tag saying which member is currently valid. */
typedef enum { T_INT, T_FLOAT, T_STR } Type;
typedef struct {
Type tag; /* which member is live */
union { int i; float f; char s[16]; } val;
} Variant;
void print_variant(const Variant *v) {
switch (v->tag) {
case T_INT: printf("int %d\n", v->val.i); break;
case T_FLOAT: printf("float %.2f\n", v->val.f); break;
case T_STR: printf("string %s\n", v->val.s); break;
}
}
int main(void) {
Variant a = { T_INT, .val.i = 42 };
Variant b = { T_FLOAT, .val.f = 3.14f };
Variant c; c.tag = T_STR; strcpy(c.val.s, "Nepal");
print_variant(&a); print_variant(&b); print_variant(&c);
printf("sizeof(Variant) = %zu\n", sizeof(Variant));
return 0;
}
Output:
int 42
float 3.14
string Nepal
sizeof(Variant) = 20
sizeof with padding for a given struct: that is a favourite numerical. Know the dot-vs-arrow rule and that struct assignment is a shallow member-wise copy.Create a free account to tick topics off, take notes as you read, watch the video lessons and get a day-by-day study plan built around your exam date.
Loading…