1๏ธโฃ Structure: one card, many details
An array can only hold things of the same type, like 5 ints. A structure can hold different types together. Think of it as a school bag that can carry a book, a pencil box and a water bottle at the same time.
struct Student { // 1. design the card (the plan)
char name[20]; // each line inside is a "member"
int roll;
float marks;
}; // semicolon at the end!
struct Student s1 = {"Anu", 101, 92.5}; // 2. make a card and fill it
s1.marks = 95; // 3. use the DOT to reach a member
| Word | Meaning |
|---|---|
struct | Keyword that starts a structure |
Tag (Student) | The name of the design |
| Member | One item inside (name, roll, marks) |
Dot . | "Open the card and take this member" |
struct Student s1;.s2.name = "Ravi";. Strings inside a structure need strcpy(s2.name, "Ravi");.Name Roll Marks
struct tag { members; };. Members are accessed with the dot operator (var.member). Memory is given only when a variable is declared, and its size is the sum of the members plus padding. For a 16-mark answer, write the syntax, declaration, initialization, accessing members and an example program like the one below.File: 01_structure_basics.c
/*
* Program 1: Structure basics
* ---------------------------
* Real-life story: Your school ID card has your NAME, ROLL NUMBER and MARKS
* all on ONE card. A structure is like that card: it keeps different kinds
* of information about ONE thing together.
*
* struct = a "school bag" that can hold a book (string),
* a pencil box (int) and a water bottle (float) together.
*/
#include <stdio.h>
#include <string.h>
/* Step 1: DESIGN the card (this makes no variable yet, just the plan) */
struct Student {
char name[20]; /* member 1: name */
int roll; /* member 2: roll number */
float marks; /* member 3: marks */
}; /* don't forget this semicolon! */
int main() {
/* Step 2: make a card and fill it while making it (initialization) */
struct Student s1 = {"Anu", 101, 92.5};
/* Step 3: make an empty card and fill it later using the DOT (.) */
struct Student s2;
strcpy(s2.name, "Ravi"); /* strings need strcpy, not = */
s2.roll = 102;
s2.marks = 88.0;
/* Step 4: read the members using the dot */
printf("Card 1 -> Name: %s, Roll: %d, Marks: %.1f\n", s1.name, s1.roll, s1.marks);
printf("Card 2 -> Name: %s, Roll: %d, Marks: %.1f\n", s2.name, s2.roll, s2.marks);
/* Change one member */
s2.marks = s2.marks + 5; /* Ravi got 5 bonus marks */
printf("After bonus, %s has %.1f marks\n", s2.name, s2.marks);
/* Copy a whole structure in one go */
struct Student s3 = s1;
printf("Copy of card 1 -> %s %d %.1f\n", s3.name, s3.roll, s3.marks);
printf("Size of one Student card = %zu bytes\n", sizeof(struct Student));
return 0;
}
Output
Card 1 -> Name: Anu, Roll: 101, Marks: 92.5 Card 2 -> Name: Ravi, Roll: 102, Marks: 88.0 After bonus, Ravi has 93.0 marks Copy of card 1 -> Anu 101 92.5 Size of one Student card = 28 bytes
2๏ธโฃ Nested structure: a box inside a box
struct Date { int day, month, year; };
struct Student { char name[20]; int roll; struct Date dob; };
s.dob.year // big box . small box . item
name = "Meena"
roll = 7
day = 15
month = 8
year = 2010
s.name โ "Meena"s.dob โ the whole dates.dob.day โ 15s.dob.year โ 2010Date for other things, like a joining date.outer.inner.member. You can define it in two ways: (1) separate structures, or (2) an embedded structure declared inside the outer one.File: 02_nested_structure.c
/*
* Program 2: Nested structure (a structure inside a structure)
* ------------------------------------------------------------
* Real-life story: A student card has a small box for DATE OF BIRTH.
* The date itself has day, month and year. So we put a small
* "Date" card INSIDE the big "Student" card, like a small box inside a big box.
*/
#include <stdio.h>
struct Date { /* small box */
int day;
int month;
int year;
};
struct Student { /* big box */
char name[20];
int roll;
struct Date dob; /* the small box lives inside the big box */
};
int main() {
struct Student s = {"Meena", 7, {15, 8, 2010}}; /* inner { } fills the date */
/* use the dot TWICE: big box . small box . item */
printf("Name : %s\n", s.name);
printf("Roll : %d\n", s.roll);
printf("Born : %02d/%02d/%d\n", s.dob.day, s.dob.month, s.dob.year);
/* birthday party next year! */
s.dob.year = s.dob.year + 1;
printf("Changed year to: %d\n", s.dob.year);
return 0;
}
Output
Name : Meena Roll : 7 Born : 15/08/2010 Changed year to: 2011
3๏ธโฃ Pointer to structure: the arrow ->
struct Book b1;
struct Book *p = &b1; // p remembers WHERE b1 lives
p->price // go to that address and take price
(*p).price // the same thing, the long way
| You have... | Use | Example |
|---|---|---|
| The structure itself | dot . | b1.price |
| A pointer to the structure | arrow -> | p->price |
*p.price is wrong because . runs before *. Write (*p).price or simply p->price.giveDiscount(&b1)) lets the function change the real book. It's also faster than copying the whole structure.struct Book *p = &b1;. Members are accessed with the arrow operator (p->member), which means the same as (*p).member. Uses: passing structures to functions by reference, dynamic structures and linked lists.File: 03_pointer_to_structure.c
/*
* Program 3: Pointer to structure (the arrow ->)
* ----------------------------------------------
* Real-life story: Instead of carrying your friend's whole toy box,
* you keep a NOTE with the box's address. Using that note you can
* open the box and play with the toys.
*
* p = &box; -> write the address of the box on the note
* p->toy -> "go to the address and open the toy"
* (*p).toy -> same thing, longer way of writing it
*/
#include <stdio.h>
struct Book {
char title[30];
int pages;
float price;
};
/* A function that gets the ADDRESS, so it can change the real book */
void giveDiscount(struct Book *b) {
b->price = b->price - 50; /* changes the original book */
}
int main() {
struct Book b1 = {"Panchatantra", 120, 250.0};
struct Book *p = &b1; /* p holds the address of b1 */
printf("Using dot : %s, %d pages, Rs %.2f\n", b1.title, b1.pages, b1.price);
printf("Using arrow : %s, %d pages, Rs %.2f\n", p->title, p->pages, p->price);
printf("Using (*p). : %s\n", (*p).title);
p->pages = 130; /* change through the pointer */
printf("\nNew page count (b1.pages) = %d\n", b1.pages);
giveDiscount(&b1); /* send the address */
printf("Price after discount = Rs %.2f\n", b1.price);
return 0;
}
Output
Using dot : Panchatantra, 120 pages, Rs 250.00 Using arrow : Panchatantra, 120 pages, Rs 250.00 Using (*p). : Panchatantra New page count (b1.pages) = 130 Price after discount = Rs 200.00
4๏ธโฃ Array of structures: a stack of report cards
struct Student cls[5]; // 5 cards in a row
cls[2].marks // card number 2, its marks
struct Student s[50];. You reach a member with s[i].member and usually go through all of them with a loop. It's used for records like a student list or an employee list. Typical programs: find the topper, average marks, sort by marks.File: 04_array_of_structures.c
/*
* Program 4: Array of structures (find the topper)
* ------------------------------------------------
* Real-life story: The teacher has a STACK of 5 report cards.
* Each card is a structure. The whole stack is an array.
* Let's find who got the highest marks (the topper!).
*/
#include <stdio.h>
struct Student {
char name[20];
int marks;
};
int main() {
struct Student cls[5] = { /* 5 cards in a row */
{"Anu", 78},
{"Ravi", 91},
{"Meena", 85},
{"Kiran", 95},
{"Divya", 66}
};
int i, total = 0, top = 0; /* top = position of the best card so far */
printf("%-8s %s\n", "Name", "Marks");
printf("--------------\n");
for (i = 0; i < 5; i++) {
printf("%-8s %d\n", cls[i].name, cls[i].marks); /* card i, member marks */
total = total + cls[i].marks;
if (cls[i].marks > cls[top].marks) {
top = i; /* found a better card */
}
}
printf("\nClass average : %.2f\n", (float)total / 5);
printf("Topper : %s with %d marks\n", cls[top].name, cls[top].marks);
printf("\nStudents who passed (marks >= 70):\n");
for (i = 0; i < 5; i++) {
if (cls[i].marks >= 70) {
printf(" %s\n", cls[i].name);
}
}
return 0;
}
Output
Name Marks -------------- Anu 78 Ravi 91 Meena 85 Kiran 95 Divya 66 Class average : 83.00 Topper : Kiran with 95 marks Students who passed (marks >= 70): Anu Ravi Meena Kiran
5๏ธโฃ Self-referential structure: the treasure hunt
struct Clue {
char message[40];
struct Clue *next; // a pointer to the SAME kind of structure
};
struct Clue next;). That would be a box containing a box containing a box... forever! It can only hold a pointer to itself, which is just an address.struct node { int data; struct node *next; };File: 05_self_referential.c
/*
* Program 5: Self-referential structure
* -------------------------------------
* Real-life story: A TREASURE HUNT. Each clue card has a message AND
* tells you where the NEXT clue card is hidden. The last card says
* "no more clues" (NULL).
*
* A self-referential structure has a pointer to ITS OWN type inside it.
* This is the building block of a linked list.
*/
#include <stdio.h>
#include <stddef.h> /* for NULL */
struct Clue {
char message[40];
struct Clue *next; /* points to another Clue (same type!) */
};
int main() {
/* make 3 clue cards */
struct Clue c3 = {"Treasure is under the bed!", NULL}; /* last card */
struct Clue c2 = {"Look in the kitchen", &c3}; /* points to c3 */
struct Clue c1 = {"Start at the door", &c2}; /* points to c2 */
struct Clue *now = &c1; /* we start with the first card */
int step = 1;
while (now != NULL) { /* keep going until "no more clues" */
printf("Clue %d: %s\n", step, now->message);
now = now->next; /* jump to the next card */
step++;
}
printf("Hunt finished!\n");
return 0;
}
Output
Clue 1: Start at the door Clue 2: Look in the kitchen Clue 3: Treasure is under the bed! Hunt finished!
6๏ธโฃ Dynamic Memory Allocation: renting chairs
Static memory (like int a[100];) is fixed when you write the program. Dynamic memory is asked for while the program runs, from a big area called the heap. These functions live in <stdlib.h>.
| Function | Party story | Syntax | Starts with |
|---|---|---|---|
malloc | Rent chairs (they may be dusty) | p = (int*)malloc(n * sizeof(int)); | Garbage |
calloc | Rent cleaned chairs | p = (int*)calloc(n, sizeof(int)); | All zeros |
realloc | More friends came, swap for a bigger set | p = (int*)realloc(p, newSize); | Old values kept |
free | Give the chairs back | free(p); | Nothing |
free(), those chairs are never returned. In a long-running program the shop eventually runs out of chairs. Also, always check whether malloc returned NULL (the shop said "no chairs left").malloc(), calloc(), realloc() and free() (header stdlib.h). malloc takes one argument and leaves garbage values. calloc takes two arguments (n, size) and sets everything to zero. realloc changes the size of an existing block. free releases it. Advantages: no wasted memory, and the size is decided at run time.File: 06_dynamic_memory.c
/*
* Program 6: Dynamic Memory Allocation (malloc, calloc, realloc, free)
* --------------------------------------------------------------------
* Real-life story: At a birthday party you don't know how many friends
* will come. Instead of buying 100 chairs, you RENT chairs when
* friends arrive, and RETURN them when the party ends.
*
* malloc -> rent chairs (they may be dusty: garbage values)
* calloc -> rent chairs that are already cleaned (set to 0)
* realloc -> more friends came, rent a bigger set of chairs
* free -> return the chairs (or the shop runs out = memory leak!)
*/
#include <stdio.h>
#include <stdlib.h> /* malloc, calloc, realloc, free live here */
int main() {
int n = 3, i;
/* ---- malloc: ask for space for 3 ints ---- */
int *marks = (int *)malloc(n * sizeof(int));
if (marks == NULL) { /* always check! the shop may say NO */
printf("No memory!\n");
return 1;
}
for (i = 0; i < n; i++) {
marks[i] = (i + 1) * 10; /* fill: 10 20 30 */
}
printf("malloc : ");
for (i = 0; i < n; i++) printf("%d ", marks[i]);
printf("\n");
/* ---- realloc: 2 more friends came, grow to 5 ---- */
int *bigger = (int *)realloc(marks, 5 * sizeof(int));
if (bigger == NULL) {
free(marks);
return 1;
}
marks = bigger;
marks[3] = 40;
marks[4] = 50;
printf("realloc : ");
for (i = 0; i < 5; i++) printf("%d ", marks[i]);
printf("\n");
/* ---- calloc: 4 ints, all cleaned to 0 ---- */
int *scores = (int *)calloc(4, sizeof(int));
if (scores == NULL) {
free(marks);
return 1;
}
printf("calloc : ");
for (i = 0; i < 4; i++) printf("%d ", scores[i]);
printf(" (all zero!)\n");
/* ---- free: give the memory back ---- */
free(marks);
free(scores);
marks = NULL; /* good habit: don't keep an old address */
scores = NULL;
printf("All memory returned with free(). Party over!\n");
return 0;
}
Output
malloc : 10 20 30 realloc : 10 20 30 40 50 calloc : 0 0 0 0 (all zero!) All memory returned with free(). Party over!
7๏ธโฃ Singly Linked List: the train
head) only knows the first coach. The last coach is hooked to nothing (NULL).Boxes glued side by side. Fixed size. To insert in the middle you must shift everything.
Coaches can be anywhere in memory. Grows and shrinks. To insert you just change hooks (pointers).
Value:
How each operation works
| Operation | Steps |
|---|---|
| Insert at front | 1. Make a new node. 2. new->next = head. 3. head = new. |
| Insert at end | 1. Make a new node. 2. Walk to the last node (t->next == NULL). 3. t->next = new. |
| Delete | 1. Find the node and remember the one before it (prev). 2. prev->next = t->next. 3. free(t). |
| Display / count | Start at head and keep doing t = t->next until NULL. |
File: 07_linked_list.c
/*
* Program 7: Singly Linked List
* -----------------------------
* Real-life story: A TRAIN. Each coach (node) carries passengers (data)
* and is hooked to the NEXT coach. The engine knows only the first
* coach (head). The last coach is hooked to nothing (NULL).
*
* head -> [10|*] -> [20|*] -> [30|NULL]
*
* We can add coaches at the front or back and remove a coach,
* without moving the other coaches. Arrays can't do that easily!
*/
#include <stdio.h>
#include <stdlib.h>
struct Node {
int data; /* passengers in this coach */
struct Node *next; /* hook to the next coach */
};
/* make a brand new coach */
struct Node *createNode(int value) {
struct Node *n = (struct Node *)malloc(sizeof(struct Node));
if (n == NULL) {
printf("No memory!\n");
exit(1);
}
n->data = value;
n->next = NULL;
return n;
}
/* add a coach at the FRONT (right behind the engine) */
struct Node *insertFront(struct Node *head, int value) {
struct Node *n = createNode(value);
n->next = head; /* new coach hooks to the old first coach */
return n; /* new coach is now the first */
}
/* add a coach at the END */
struct Node *insertEnd(struct Node *head, int value) {
struct Node *n = createNode(value);
if (head == NULL) {
return n; /* empty train: this is the first coach */
}
struct Node *t = head;
while (t->next != NULL) { /* walk to the last coach */
t = t->next;
}
t->next = n; /* hook the new coach at the back */
return head;
}
/* remove the first coach that has this value */
struct Node *deleteValue(struct Node *head, int value) {
struct Node *t = head, *prev = NULL;
while (t != NULL && t->data != value) {
prev = t;
t = t->next;
}
if (t == NULL) {
printf("%d not found\n", value);
return head;
}
if (prev == NULL) {
head = t->next; /* removing the first coach */
} else {
prev->next = t->next; /* unhook t, join prev to the one after t */
}
free(t); /* give the coach's memory back */
return head;
}
void display(struct Node *head) {
printf("head -> ");
while (head != NULL) {
printf("[%d] -> ", head->data);
head = head->next;
}
printf("NULL\n");
}
int count(struct Node *head) {
int c = 0;
while (head != NULL) {
c++;
head = head->next;
}
return c;
}
void freeList(struct Node *head) {
while (head != NULL) {
struct Node *nextOne = head->next;
free(head);
head = nextOne;
}
}
int main() {
struct Node *head = NULL; /* empty train */
head = insertEnd(head, 20);
head = insertEnd(head, 30);
printf("Insert 20, 30 at end : "); display(head);
head = insertFront(head, 10);
printf("Insert 10 at front : "); display(head);
head = insertEnd(head, 40);
printf("Insert 40 at end : "); display(head);
printf("Number of coaches : %d\n", count(head));
head = deleteValue(head, 30);
printf("Delete 30 : "); display(head);
head = deleteValue(head, 10);
printf("Delete 10 (first coach) : "); display(head);
printf("Number of coaches : %d\n", count(head));
freeList(head); /* return all memory */
return 0;
}
Output
Insert 20, 30 at end : head -> [20] -> [30] -> NULL Insert 10 at front : head -> [10] -> [20] -> [30] -> NULL Insert 40 at end : head -> [10] -> [20] -> [30] -> [40] -> NULL Number of coaches : 4 Delete 30 : head -> [10] -> [20] -> [40] -> NULL Delete 10 (first coach) : head -> [20] -> [40] -> NULL Number of coaches : 2
8๏ธโฃ typedef: giving a nickname
typedef gives a short nickname to a long type name.typedef old_name NickName;
typedef unsigned int Age; // now "Age x;" means "unsigned int x;"
typedef struct { char name[20]; Age age; } Person;
Person p; // no need to write "struct" every time!
typedef does not make a new type. It only gives an existing type another name. It makes code shorter and easier to read.typedef is a keyword used to create an alias (another name) for an existing data type. Syntax: typedef existing_type new_name;. It's commonly used with structures, for example typedef struct node Node;. Benefits: readability, shorter code, and easier to change later.File: 08_typedef.c
/*
* Program 8: typedef (giving a nickname)
* --------------------------------------
* Real-life story: Your friend's full name is "Venkata Subramanian",
* but everyone calls him "Venky". typedef gives a SHORT NICKNAME
* to a long type name.
*
* typedef old_long_name NickName;
*/
#include <stdio.h>
typedef unsigned int Age; /* nickname for unsigned int */
typedef struct { /* nickname for a structure */
char name[20];
Age age;
} Person; /* now write "Person" instead of "struct ..." */
typedef struct Node { /* typedef also works for linked list nodes */
int data;
struct Node *next;
} Node;
int main() {
Age myAge = 12;
Person p = {"Arjun", 12};
Node n1 = {5, NULL};
printf("My age : %u\n", myAge);
printf("Person : %s, %u years\n", p.name, p.age);
printf("Node data : %d\n", n1.data);
printf("Without typedef we would write: struct Node n1;\n");
printf("With typedef we just write : Node n1;\n");
return 0;
}
Output
My age : 12 Person : Arjun, 12 years Node data : 5 Without typedef we would write: struct Node n1; With typedef we just write : Node n1;
9๏ธโฃ Union: one cup, one drink at a time
Union = one cup. Fill it with milk or juice or water. Pour juice in and the milk is gone!
Memory picture (1 square = 1 byte)
struct LunchBox: each member gets its own room, so the size is 12 bytes
union Cup: all members share the same room, so the size is 4 bytes (the biggest member)
char c.| Structure | Union |
|---|---|
Keyword struct | Keyword union |
| Each member has its own memory | All members share one memory |
| Size = sum of members (+ padding) | Size = biggest member |
| All members can be used at once | Only one member is valid at a time |
| Changing one doesn't affect others | Changing one spoils the others |
| Used for records (a student) | Used to save memory (a value that's either int or float) |
File: 09_union.c
/*
* Program 9: Union vs Structure
* -----------------------------
* Real-life story:
* STRUCTURE = a lunch box with SEPARATE compartments.
* Rice, curd and sweet can all be inside at the same time.
* UNION = ONE single cup. You can fill it with milk OR juice OR water,
* but only ONE at a time. Pour juice in, the milk is gone!
*
* A union's size = size of its BIGGEST member (one shared space).
* A structure's size = sum of all members (+ some padding).
*/
#include <stdio.h>
struct LunchBox { /* separate rooms */
int i;
float f;
char c;
};
union Cup { /* one shared room */
int i;
float f;
char c;
};
int main() {
struct LunchBox box;
union Cup cup;
printf("Size of struct LunchBox = %zu bytes\n", sizeof(box));
printf("Size of union Cup = %zu bytes\n\n", sizeof(cup));
/* structure: everything stays */
box.i = 10;
box.f = 2.5;
box.c = 'A';
printf("Struct: i=%d f=%.1f c=%c (all are safe)\n\n", box.i, box.f, box.c);
/* union: only the LAST one you filled is correct */
cup.i = 10;
printf("Union after cup.i = 10 -> i = %d\n", cup.i);
cup.f = 2.5;
printf("Union after cup.f = 2.5 -> f = %.1f\n", cup.f);
printf(" ...now i is spoiled -> i = %d (garbage!)\n", cup.i);
cup.c = 'A';
printf("Union after cup.c = 'A' -> c = %c\n", cup.c);
return 0;
}
Output (the garbage number may differ on your computer)
Size of struct LunchBox = 12 bytes Size of union Cup = 4 bytes Struct: i=10 f=2.5 c=A (all are safe) Union after cup.i = 10 -> i = 10 Union after cup.f = 2.5 -> f = 2.5 ...now i is spoiled -> i = 1075838976 (garbage!) Union after cup.c = 'A' -> c = A
๐ Storage classes & visibility
static: a drawing in your notebook. It stays after you close the book, and you keep adding to it.
register: keeping your pencil in your hand instead of in your bag, so it's faster to grab.
extern: "The bat is at my friend's house. I'm only telling you its name."
A storage class tells 4 things about a variable: where it is stored, its default value, its scope (who can see it) and its lifetime (how long it lives).
| Class | Stored in | Default value | Scope (visibility) | Lifetime |
|---|---|---|---|---|
auto | Memory (stack) | Garbage | Inside its block { } | Until the block ends |
register | CPU register (if free) | Garbage | Inside its block { } | Until the block ends |
static | Memory (data area) | 0 | Inside its block (local) or file (global) | The whole program |
extern | Memory (data area) | 0 | Global, across files | The whole program |
Each click calls the function once.
count++ โ -
Starts again at 0 every call
count++ โ -
Remembers the old value
&fast is an error. Modern compilers usually decide about registers by themselves.static local variables keep their value between function calls. extern declares a global variable that is defined in another file. Visibility means scope: block scope, function scope, file scope and program scope.File: 10_storage_classes.c
/*
* Program 10: Storage classes (auto, register, static, extern)
* ------------------------------------------------------------
* Real-life story:
* auto -> a SAND drawing on the beach. Every time the wave (function call)
* comes, it is wiped and drawn fresh.
* static -> a drawing in your NOTEBOOK. It stays even after you close the book,
* and you can keep adding to it.
* register -> keeping your pencil IN YOUR HAND instead of in the bag (faster to reach).
* extern -> "this toy is in my friend's house, I'm just telling you its name".
*/
#include <stdio.h>
int schoolBell = 0; /* global: everyone in this file can see it (default 0) */
void visitAuto() {
auto int count = 0; /* 'auto' is the default for local variables */
count++;
printf(" auto count = %d\n", count);
}
void visitStatic() {
static int count = 0; /* made only ONCE, remembers its value */
count++;
printf(" static count = %d\n", count);
}
int main() {
int i;
for (i = 1; i <= 3; i++) {
printf("Call %d:\n", i);
visitAuto();
visitStatic();
}
register int fast; /* hint: keep it in a CPU register (can't use &fast) */
int sum = 0;
for (fast = 1; fast <= 5; fast++) {
sum += fast;
}
printf("\nregister loop sum 1..5 = %d\n", sum);
schoolBell++;
printf("global schoolBell = %d\n", schoolBell);
{ /* a small inner block */
int secret = 99; /* visible only inside these { } */
printf("inner block secret = %d\n", secret);
}
/* printf("%d", secret); <- ERROR: secret is not visible here */
return 0;
}
Output
Call 1: auto count = 1 static count = 1 Call 2: auto count = 1 static count = 2 Call 3: auto count = 1 static count = 3 register loop sum 1..5 = 15 global schoolBell = 1 inner block secret = 99
1๏ธโฃ1๏ธโฃ extern: sharing between two files
score) is kept at your friend's house (11_extern_helper.c). In your file you say extern int score;, which means "it's real, it lives in another file, please find it."| Declaration | Definition |
|---|---|
extern int score; | int score = 10; |
| Only tells the name and type | Actually creates the memory |
| Can appear many times | Only once in the whole program |
gcc 11_extern_main.c 11_extern_helper.c -o program then ./programFile: 11_extern_main.c
/*
* Program 11: extern (sharing a variable between two files)
* ---------------------------------------------------------
* Real-life story: The CRICKET BAT is kept at your friend's house
* (11_extern_helper.c). You say "extern int score;" which means:
* "score is real, but it is made in another file. Please find it."
*
* Compile BOTH files together:
* gcc 11_extern_main.c 11_extern_helper.c -o program
* ./program
*/
#include <stdio.h>
extern int score; /* declared here, CREATED in the helper file */
void addRuns(int runs); /* function from the helper file */
int main() {
printf("Score at start : %d\n", score);
addRuns(4);
addRuns(6);
printf("Score after 4, 6 : %d\n", score);
score = score + 1; /* we can change it here too */
printf("After 1 extra run: %d\n", score);
return 0;
}
File: 11_extern_helper.c
/*
* Helper file for Program 11 (extern).
* The variable "score" is really CREATED here (memory is given here).
* Compile with: gcc 11_extern_main.c 11_extern_helper.c -o program
*/
int score = 10; /* the real variable lives in this file */
void addRuns(int runs) {
score = score + runs;
}
Output
Score at start : 10 Score after 4, 6 : 20 After 1 extra run: 21
๐ 2-mark questions & answers
1. Define structure. Give its syntax.
A structure is a user-defined data type that groups related variables of different types under one name.struct tag { type member1; type member2; };2. How do you access structure members?
Use the dot operator with a structure variable (s.roll) and the arrow operator with a structure pointer (p->roll).3. What is a nested structure?
A structure that has another structure variable as one of its members, for example a Student with a Date dob. You reach the inner members withs.dob.day.4. What is a self-referential structure?
A structure with a member that is a pointer to the same structure type, likestruct node { int data; struct node *next; };. It's used in linked lists and trees.5. Differentiate malloc() and calloc().
malloc(size) takes 1 argument and leaves garbage values. calloc(n, size) takes 2 arguments and sets all bytes to zero.6. What is a memory leak?
When dynamically allocated memory is never released with free(), it stays reserved and can't be reused. The program then wastes memory.7. What is the use of realloc()?
It changes the size of a block that was already allocated (bigger or smaller) and keeps the old contents:p = realloc(p, newsize);8. What is a linked list? Give its advantages.
A linear collection of nodes, where each node has data and a pointer to the next node. Advantages: dynamic size, and insertion/deletion don't need shifting.9. Difference between structure and union?
In a structure every member has separate memory (size = sum). In a union all members share one memory (size = largest member) and only one is valid at a time.10. What is typedef?
A keyword that creates a new name (alias) for an existing type:typedef struct student Student;11. List the storage classes in C.
auto, register, static and extern.12. Why is static different from auto?
A static local variable is made only once, starts at 0 and keeps its value between function calls. An auto variable is made fresh (with a garbage value) on every call.13. What do scope and lifetime mean?
Scope is the part of the program where a variable can be used (visibility). Lifetime is how long the variable exists in memory while the program runs.๐ Mini quiz
๐ฏ Practice homework
- Make a
struct Employeewith name, id and salary. Store 3 employees and print the one with the highest salary. - Add a nested
struct Address(street, city, pin) to the Employee and print the city of each employee. - Use
mallocto make an array whose size the user types in. Read the numbers and print their sum. Don't forgetfree! - Add a
search(head, value)function to the linked list program that prints the position of the value or "not found". - Add
insertAtPosition(head, pos, value)to the linked list. - Make a
unionwithint,doubleandchar[10]. Predict its size, then check withsizeof. - Write a function with a
staticcounter that prints "You called me N times".