Structures, Unions & Bit Fields
নিজের type বানানো — composite data
1. Your Own Types
একটি struct সম্পর্কযুক্ত কয়েকটি field-কে একটি ইউনিটে গ্রুপ করে। এটি প্রতিটি non-trivial data structure-এর ভিত্তি।
#include <stdio.h>
struct Student {
char name[50];
int id;
double gpa;
};
int main(void) {
struct Student s = {"Arif", 201, 3.85};
printf("%s (ID %d): %.2f\n", s.name, s.id, s.gpa);
return 0;
}
2. typedef for Readability
#include <stdio.h>
typedef struct { double x, y; } Point;
double mag2(Point p) { return p.x * p.x + p.y * p.y; }
int main(void) {
Point p = { 3.0, 4.0 };
printf("|p|^2 = %.2f\n", mag2(p));
return 0;
}
typedef করলে আর struct Student লিখতে হয় না — শুধু Student। Code পড়া সহজ হয়।3. Access — Dot vs Arrow
Point p;
p.x = 5; // direct access
Point *pp = &p;
pp->x = 5; // through pointer — same as (*pp).x
4. Nested Structs and Arrays of Structs
#include <stdio.h>
typedef struct { double x, y; } Point;
typedef struct { Point start, end; } Line;
int main(void) {
Line l = { {0, 0}, {3, 4} };
printf("start=(%.1f, %.1f) end=(%.1f, %.1f)\n",
l.start.x, l.start.y, l.end.x, l.end.y);
Point poly[3] = { {0,0}, {1,0}, {0,1} };
for (int i = 0; i < 3; i++)
printf("vertex %d = (%.1f, %.1f)\n", i, poly[i].x, poly[i].y);
return 0;
}
5. Struct Padding & Alignment
Compiler প্রতিটি field-কে "natural alignment"-এ রাখে, তাই struct-এর ভেতর ফাঁক (padding) থাকে।
struct {char; int;} সাধারণত 8 byte।
#include <stdio.h>
struct A { char c; int i; }; // often 8 bytes
struct B { int i; char c; }; // also 8 bytes (trailing padding)
struct C { int i; char a; char b; char c; char d; }; // 8 bytes
int main(void) {
printf("sizeof(A) = %zu\n", sizeof(struct A));
printf("sizeof(B) = %zu\n", sizeof(struct B));
printf("sizeof(C) = %zu\n", sizeof(struct C));
return 0;
}
6. Unions — One Memory, Many Views
#include <stdio.h>
union Data {
int i;
float f;
char bytes[4];
};
int main(void) {
union Data d;
d.i = 0x41424344; // 'A','B','C','D' on little-endian
printf("as int : 0x%X\n", d.i);
printf("bytes : %c %c %c %c\n", d.bytes[0], d.bytes[1], d.bytes[2], d.bytes[3]);
printf("size : %zu\n", sizeof(union Data));
return 0;
}
7. Bit Fields — Compact Packing
#include <stdio.h>
struct Flags {
unsigned int read : 1;
unsigned int write : 1;
unsigned int exec : 1;
unsigned int level : 5; // 5-bit int: 0..31
};
int main(void) {
struct Flags f = { 1, 1, 0, 7 };
printf("r=%u w=%u x=%u lvl=%u size=%zu\n",
f.read, f.write, f.exec, f.level, sizeof f);
return 0;
}
Bit field-এর layout (bit ordering, padding) implementation-defined — তাই network protocol cross-platform binary-format-এ bit field-এর উপর ভরসা না করাই ভালো। Embedded system-এ hardware register-এর জন্য কার্যকর।
8. Passing Structs to Functions
void print_point(const Point *p) { // prefer pointer — no copy
printf("(%.2f, %.2f)\n", p->x, p->y);
}
ছোট struct (≤ 16 bytes) pass-by-value ঠিক আছে। বড় struct-এ pointer pass-by-value-এর চেয়ে দ্রুত (কপি হয় না)।
9. Practice Problems
- Define a
Datestruct (day, month, year) and writeprint_date.Datestruct বানান ওprint_dateলিখুন।✨ Show Answer
date.c#include <stdio.h> typedef struct { int d, m, y; } Date; void print_date(Date x) { printf("%02d-%02d-%04d\n", x.d, x.m, x.y); } int main(void) { print_date((Date){16, 12, 2026}); return 0; } - Write
int compare_dates(const Date *, const Date *).দুটিDateতুলনা করার ফাংশন লিখুন।✨ Show Answer
cmp_date.c#include <stdio.h> typedef struct { int d, m, y; } Date; int compare_dates(const Date *a, const Date *b) { if (a->y != b->y) return a->y - b->y; if (a->m != b->m) return a->m - b->m; return a->d - b->d; } int main(void) { Date a = {10, 3, 2026}, b = {1, 4, 2026}; int c = compare_dates(&a, &b); puts(c < 0 ? "a < b" : c == 0 ? "a == b" : "a > b"); return 0; } - Define a
Rectanglewith two Points and compute its area and perimeter.দুটি Point দিয়ে Rectangle ঘোষণা করুন এবং area/perimeter বের করুন।✨ Show Answer
rect.c#include <stdio.h> #include <math.h> typedef struct { double x, y; } Point; typedef struct { Point tl, br; } Rect; int main(void) { Rect r = { {0,4}, {3,0} }; double w = fabs(r.br.x - r.tl.x); double h = fabs(r.tl.y - r.br.y); printf("area=%.2f perim=%.2f\n", w * h, 2 * (w + h)); return 0; } - Build an array of Students and print them sorted by GPA (descending).Student-এর array বানিয়ে GPA-এর descending ক্রমে প্রিন্ট করুন।
✨ Show Answer
sort_students.c#include <stdio.h> #include <stdlib.h> typedef struct { char name[32]; double gpa; } Student; int by_gpa_desc(const void *a, const void *b) { double d = ((const Student *)b)->gpa - ((const Student *)a)->gpa; return (d > 0) - (d < 0); } int main(void) { Student s[] = { {"Arif",3.72}, {"Nusrat",3.92}, {"Zahid",3.55} }; int n = 3; qsort(s, n, sizeof s[0], by_gpa_desc); for (int i = 0; i < n; i++) printf("%s : %.2f\n", s[i].name, s[i].gpa); return 0; } - Show the size of
struct { char; int; }and explain padding.struct { char; int; }-এর size দেখান ও padding ব্যাখ্যা করুন।✨ Show Answer
Section 5-এর
padding.c-ই সম্পূর্ণ উত্তর — output-এ সাধারণত 8, 8, 8 আসবে। - Use
__attribute__((packed))(GCC) to remove padding and compare sizes.GCC-তে__attribute__((packed))দিয়ে padding সরিয়ে size তুলনা করুন।✨ Show Answer
packed.c#include <stdio.h> struct A { char c; int i; }; struct __attribute__((packed)) B { char c; int i; }; int main(void) { printf("sizeof(A)=%zu\n", sizeof(struct A)); printf("sizeof(B)=%zu\n", sizeof(struct B)); return 0; }Packed struct-এ misaligned access-এর কারণে কিছু আর্কিটেকচারে (ARM) performance কমতে পারে।
- Define a tagged union (enum + union) for variant values: int, float, string.Tagged union (enum + union) বানান — int, float, string variant-এর জন্য।
✨ Show Answer
variant.c#include <stdio.h> typedef enum { VAL_INT, VAL_FLT, VAL_STR } Tag; typedef struct { Tag tag; union { int i; float f; const char *s; } u; } Value; void print_value(Value v) { switch (v.tag) { case VAL_INT: printf("int: %d\n", v.u.i); break; case VAL_FLT: printf("flt: %.2f\n", v.u.f); break; case VAL_STR: printf("str: %s\n", v.u.s); break; } } int main(void) { print_value((Value){VAL_INT, .u.i = 42}); print_value((Value){VAL_FLT, .u.f = 3.14f}); print_value((Value){VAL_STR, .u.s = "ABCL"}); return 0; } - Use a union to read the individual bytes of an int.Union দিয়ে একটি int-এর byte গুলো পড়ুন।
✨ Show Answer
উপরের Section 6-এর
union.c-ই উত্তর। - Detect endianness with a union.Union দিয়ে endianness detect করুন।
✨ Show Answer
endian.c#include <stdio.h> int main(void) { union { int i; char c[sizeof(int)]; } u; u.i = 1; puts(u.c[0] == 1 ? "Little-endian" : "Big-endian"); return 0; } - Define a bit field for a small CPU flags register (carry, zero, sign, overflow, 4-bit priv).ছোট CPU flags register-এর জন্য bit field ঘোষণা করুন।
✨ Show Answer
cpu_flags.c#include <stdio.h> struct CPU { unsigned int carry : 1; unsigned int zero : 1; unsigned int sign : 1; unsigned int over : 1; unsigned int priv : 4; }; int main(void) { struct CPU f = { 1, 0, 1, 0, 3 }; printf("C=%u Z=%u S=%u O=%u priv=%u size=%zu\n", f.carry, f.zero, f.sign, f.over, f.priv, sizeof f); return 0; } - Build a linked-list node struct and write
push_front.Linked-list node বানান ওpush_frontলিখুন।✨ Show Answer
list_push.c#include <stdio.h> #include <stdlib.h> typedef struct Node { int v; struct Node *next; } Node; void push_front(Node **head, int v) { Node *n = malloc(sizeof *n); n->v = v; n->next = *head; *head = n; } void print_list(Node *h) { for (; h; h = h->next) printf("%d ", h->v); putchar('\n'); } int main(void) { Node *head = NULL; for (int i = 1; i <= 5; i++) push_front(&head, i); print_list(head); while (head) { Node *t = head; head = head->next; free(t); } return 0; } - Pass a struct by value vs by pointer — and see performance difference.Struct pass-by-value vs pass-by-pointer — performance পার্থক্য।
✨ Show Answer
ছোট struct-এ পার্থক্য সামান্য; বড় struct (যেমন 1 KB-র matrix) pass-by-value প্রতিবার পুরো কপি করবে — বাস্তব programming-এ কখনোই pass-by-value করবেন না বড় struct-কে। সবসময়
const SomeType *ব্যবহার করুন যদি modify না করতে চান। - Implement
Point add(Point, Point)that returns a struct.Struct return করার ফাংশনPoint addলিখুন।✨ Show Answer
add_point.c#include <stdio.h> typedef struct { double x, y; } Point; Point add(Point a, Point b) { return (Point){ a.x + b.x, a.y + b.y }; } int main(void) { Point p = add((Point){1,2}, (Point){3,4}); printf("(%.1f, %.1f)\n", p.x, p.y); return 0; } - Build a self-referential struct (
struct Node { ...; struct Node *next; };).Self-referential struct বানান।✨ Show Answer
Problem 11-এর
list_push.c-ই self-referential struct দেখায়। Field type হিসেবে নিজেই একটি pointer থাকে, কিন্তু সরাসরিstruct Node inside struct Node(pointer ছাড়া) চলবে না — infinite size। - Initialize a struct using designated initializers
{.x = 1, .y = 2}.Designated initializer ব্যবহার করে struct init করুন।✨ Show Answer
designated.c#include <stdio.h> typedef struct { int id; double x, y, z; } Point3; int main(void) { Point3 p = { .id = 7, .x = 1.0, .y = 2.0, .z = 3.0 }; printf("id=%d (%.1f, %.1f, %.1f)\n", p.id, p.x, p.y, p.z); return 0; }C99 designated initializer — field নাম দিয়ে নির্দিষ্টভাবে initialize করা যায়, অর্ডার লাগে না।
- Why can't you put
struct Foodirectly inside itself (without a pointer)?struct Foo-র ভেতরে সরাসরি নিজেই কেন রাখা যায় না?✨ Show Answer
সরাসরি রাখলে
struct Foo-র size হবে = তার নিজের size + ... — যা infinite। তাই C-তে এটি অনুমোদিত নয়। Pointer ব্যবহার করলে সমস্যা নেই — pointer-এর size fixed (4 বা 8 byte)। - Reorder fields to minimize padding — show the improvement.Field পুনর্বিন্যাস করে padding কমান — উন্নতি দেখান।
✨ Show Answer
reorder.c#include <stdio.h> struct Bad { char a; double b; char c; int d; }; // lots of padding struct Good { double b; int d; char a; char c; }; // big → small int main(void) { printf("Bad = %zu\n", sizeof(struct Bad)); printf("Good = %zu\n", sizeof(struct Good)); return 0; } - Define a struct for an IPv4 header using bit fields (simplified).IPv4 header-এর জন্য bit field-ভিত্তিক struct লিখুন (সরলীকৃত)।
✨ Show Answer
ipv4.c#include <stdio.h> struct IPv4 { unsigned int version : 4; unsigned int ihl : 4; unsigned int tos : 8; unsigned int total : 16; }; int main(void) { struct IPv4 h = { 4, 5, 0, 1500 }; printf("ver=%u ihl=%u tos=%u total=%u size=%zu\n", h.version, h.ihl, h.tos, h.total, sizeof h); return 0; }বাস্তবে IPv4 parser-এ bit field-এর পরিবর্তে manual bit masking বেশি portable, কারণ bit layout implementation-নির্ভর।
Glossary (শব্দকোষ)
| Term | Meaning | বাংলায় |
|---|---|---|
struct | A user-defined type grouping multiple fields. | একাধিক field একসাথে রাখা user-defined type। |
union | Like a struct, but all fields share the same memory. | সব field একই memory ভাগাভাগি করে। |
| Member / Field | One named component inside a struct or union. | Struct/union-এর ভিতরের একটি নামকরা component। |
Member Access (.) | Access a member of a struct value. | Struct-এর field access করার operator। |
Arrow (->) | Access a member through a pointer to a struct. | Pointer-এর মাধ্যমে struct field access। |
typedef | Creates an alias for an existing type. | Type-এর জন্য alias তৈরি। |
| Padding | Bytes inserted between fields for alignment. | Alignment-এর জন্য field-এর মাঝে যোগ হওয়া byte। |
| Alignment | The required address-multiple for a type's storage. | Type-এর সংরক্ষণে যে address-multiple দরকার। |
| Bit Field | A struct member with explicit bit width. | নির্দিষ্ট bit-width-যুক্ত struct member। |
| Designated Initializer | {.x = 1} syntax to set members by name. | নাম ধরে field initialize করার গঠন। |
| Tagged Union | A struct combining a union with a "type" field. | Type-tag সহ union — কোন variant সক্রিয় তা বোঝাতে। |
| Forward Declaration | Declaring a struct name before its full definition. | পূর্ণ সংজ্ঞার আগেই struct-এর নাম ঘোষণা। |
Summary — Module 18
struct groups data; union overlays it. typedef cleans up syntax. Know padding — it surprises beginners. Bit fields and unions let you get close to the bytes. Pass large structs by pointer.