1. Modular programming
A function is a helper with a name that does one job. main() is the boss that calls the helpers.
Breaking a big program into small functions is called modular programming (each function is a "module").
Write once, call many times.
A small helper is easy to check.
Different people write different functions.
bakeCake(); tells you what happens.File: 01_modular_programming.c
/*
* Program 1: Modular Programming
* ------------------------------
* Real-life story: Making a birthday party.
* Mom does not do everything alone. She gives jobs to helpers:
* - one helper decorates
* - one helper bakes the cake
* - one helper sings the song
* Each helper = one FUNCTION. main() is Mom, who calls the helpers.
*
* Breaking a big program into small functions is called MODULAR PROGRAMMING.
*/
#include <stdio.h>
void decorate() { /* helper 1 */
printf("Helper 1: Balloons are up!\n");
}
void bakeCake() { /* helper 2 */
printf("Helper 2: Cake is ready!\n");
}
void singSong() { /* helper 3 */
printf("Helper 3: Happy birthday to you!\n");
}
int main() { /* Mom, the boss */
printf("Party planning starts...\n");
decorate(); /* call helper 1 */
bakeCake(); /* call helper 2 */
singSong(); /* call helper 3 */
singSong(); /* we can call a helper again and again! */
printf("Party done!\n");
return 0;
}
Output
Party planning starts... Helper 1: Balloons are up! Helper 2: Cake is ready! Helper 3: Happy birthday to you! Helper 3: Happy birthday to you! Party done!
2. Function prototype, definition and call
| Part | Juice shop | Example | Where |
|---|---|---|---|
| Prototype (declaration) | Menu board | int addFruits(int a, int o); | Above main, ends with ; |
| Definition | Kitchen | int addFruits(int a, int o) { return a + o; } | Anywhere, has a body { } |
| Call | Ordering | total = addFruits(3, 2); | Inside another function |
return_type function_name ( parameter list )
int addFruits ( int apples, int oranges )
โ โ โ
โ โ โโ what goes IN (formal parameters)
โ โโ the helper's name
โโ what comes OUT (void = nothing)
apples: oranges:
return sends one value back and ends the function.File: 02_prototype_definition_call.c
/*
* Program 2: Function Prototype, Definition and Call
* --------------------------------------------------
* Real-life story: A juice shop.
* PROTOTYPE = the menu board: "Juice: give 2 fruits, get 1 juice"
* (tells the name, what goes in, what comes out)
* DEFINITION = the kitchen: how the juice is actually made
* CALL = you ordering: "One juice with 3 apples and 2 oranges, please!"
*/
#include <stdio.h>
/* 1. PROTOTYPE (declaration): return type, name, parameter types, then ; */
int addFruits(int apples, int oranges);
int main() {
int total;
/* 3. CALL: we send 3 and 2 (actual arguments) */
total = addFruits(3, 2);
printf("Total fruits in the juice = %d\n", total);
/* call again with different values */
printf("Another juice uses %d fruits\n", addFruits(5, 4));
return 0;
}
/* 2. DEFINITION: the real work. apples and oranges are formal parameters */
int addFruits(int apples, int oranges) {
int sum = apples + oranges;
return sum; /* send the answer back to whoever called */
}
Output
Total fruits in the juice = 5 Another juice uses 9 fruits
3. The 4 types of functions
| # | Type | Give something? | Get something back? | Prototype |
|---|---|---|---|---|
| 1 | No arguments, no return | โ | โ | void sayHi(void); |
| 2 | With arguments, no return | โ | โ | void greet(int rollNo); |
| 3 | No arguments, with return | โ | โ | int getAge(void); |
| 4 | With arguments, with return | โ | โ | int multiply(int a, int b); |
File: 03_function_categories.c
/*
* Program 3: The 4 kinds of functions
* -----------------------------------
* Real-life story: Talking to friends.
* 1. No arguments, no return : friend just says "Hi!" (you give nothing, get nothing)
* 2. Arguments, no return : you give a name, friend shouts it (you give, get nothing back)
* 3. No arguments, with return : friend tells you their age (you give nothing, get a value)
* 4. Arguments, with return : you give 2 numbers, friend adds (you give, and get a value)
*/
#include <stdio.h>
void sayHi(void); /* type 1 */
void greet(int rollNo); /* type 2 */
int getAge(void); /* type 3 */
int multiply(int a, int b); /* type 4 */
int main() {
sayHi(); /* 1 */
greet(25); /* 2 */
int age = getAge(); /* 3 */
printf("Friend's age is %d\n", age);
int ans = multiply(6, 7); /* 4 */
printf("6 x 7 = %d\n", ans);
return 0;
}
void sayHi(void) {
printf("Type 1: Hi!\n");
}
void greet(int rollNo) {
printf("Type 2: Hello roll number %d!\n", rollNo);
}
int getAge(void) {
printf("Type 3: ");
return 12;
}
int multiply(int a, int b) {
printf("Type 4: ");
return a * b;
}
Output
Type 1: Hi! Type 2: Hello roll number 25! Type 3: Friend's age is 12 Type 4: 6 x 7 = 42
4. Built-in string functions
| Function | Header | Does | Example โ result |
|---|---|---|---|
strlen(s) | string.h | Counts letters (not '\0') | strlen("Ravi") โ 4 |
strcpy(a, b) | string.h | Copies b into a | a becomes "Ravi" |
strcat(a, b) | string.h | Glues b to the end of a | "Ravi" + " Kumar" โ "Ravi Kumar" |
strcmp(a, b) | string.h | 0 if same, negative if a comes first, positive if b comes first | strcmp("cat","dog") โ negative |
toupper(c) / tolower(c) | ctype.h | Change one letter's case | toupper('r') โ 'R' |
strrev(s) | not standard | Reverse (only some old compilers have it) | Write your own loop instead |
strcpy and strcat, the target array must be big enough. char first[30] has room; char first[] = "Ravi" only has room for 5 characters.a: b:
#include <string.h>. For strcmp, say it compares character by character using ASCII values.File: 04_string_functions.c
/*
* Program 4: Built-in STRING functions (#include <string.h>, <ctype.h>)
* ----------------------------------------------------------------------
* Real-life story: Name stickers for school books.
* C gives us ready-made helpers so we don't write everything ourselves.
*
* strlen(s) -> how many letters
* strcpy(a, b) -> copy b into a (photocopy)
* strcat(a, b) -> stick b at end of a (glue)
* strcmp(a, b) -> 0 if same, <0 or >0 if different
* toupper(ch) -> make one letter CAPITAL
* strrev is NOT standard C, so we reverse with our own loop.
*/
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int main() {
char first[30] = "Ravi";
char last[] = "Kumar";
char copy[30];
int i, len;
/* strlen */
printf("strlen(\"%s\") = %lu letters\n", first, (unsigned long)strlen(first));
/* strcpy: photocopy first into copy */
strcpy(copy, first);
printf("strcpy -> copy now has \"%s\"\n", copy);
/* strcat: glue a space and the last name to first */
strcat(first, " ");
strcat(first, last);
printf("strcat -> full name \"%s\"\n", first);
/* strcmp: compare words */
printf("strcmp(\"cat\", \"cat\") = %d (same)\n", strcmp("cat", "cat"));
printf("strcmp(\"cat\", \"dog\") is %s (c comes before d)\n",
strcmp("cat", "dog") < 0 ? "negative" : "positive");
/* toupper: one letter at a time */
for (i = 0; first[i] != '\0'; i++) {
first[i] = toupper(first[i]);
}
printf("toupper -> \"%s\"\n", first);
/* reverse (our own strrev) : swap first and last letters, move inward */
len = strlen(copy);
for (i = 0; i < len / 2; i++) {
char temp = copy[i];
copy[i] = copy[len - 1 - i];
copy[len - 1 - i] = temp;
}
printf("reverse -> \"%s\"\n", copy);
return 0;
}
Output
strlen("Ravi") = 4 letters
strcpy -> copy now has "Ravi"
strcat -> full name "Ravi Kumar"
strcmp("cat", "cat") = 0 (same)
strcmp("cat", "dog") is negative (c comes before d)
toupper -> "RAVI KUMAR"
reverse -> "ivaR"
5. Built-in math functions
| Function | Does | Example |
|---|---|---|
sqrt(x) | Square root | sqrt(49) = 7 |
pow(x, y) | x to the power y | pow(2, 3) = 8 |
abs(x) | Remove minus sign (int, in stdlib.h) | abs(-5) = 5 |
fabs(x) | Same for decimals | fabs(-2.5) = 2.5 |
ceil(x) | Round UP | ceil(4.2) = 5 |
floor(x) | Round DOWN | floor(9.8) = 9 |
-lm at the end: gcc 05_math_functions.c -o program -lm. It tells gcc to link the math library. On Mac it works without it, but adding it does no harm.x: y:
<math.h>, functions return double. Know the difference between ceil and floor with an example.File: 05_math_functions.c
/*
* Program 5: Built-in MATH functions (#include <math.h>)
* -------------------------------------------------------
* Real-life story: A garden.
* sqrt -> a square garden has area 49. How long is one side? sqrt(49) = 7
* pow -> 3 rows, each row doubles... 2 to the power 3 = 8
* abs -> distance is never negative: abs(-5) = 5
* ceil -> 4.2 buses needed? You must book 5 buses (round UP)
* floor -> Rs 9.8 in pocket, how many Rs 1 toffees? 9 (round DOWN)
*
* IMPORTANT: compile with -lm to link the math library:
* gcc 05_math_functions.c -o program -lm
*/
#include <stdio.h>
#include <math.h>
#include <stdlib.h> /* abs() for int lives here */
int main() {
printf("sqrt(49) = %.1f\n", sqrt(49));
printf("pow(2, 3) = %.1f\n", pow(2, 3));
printf("abs(-5) = %d\n", abs(-5));
printf("fabs(-2.5) = %.1f\n", fabs(-2.5));
printf("ceil(4.2) = %.1f\n", ceil(4.2));
printf("floor(9.8) = %.1f\n", floor(9.8));
/* real use: 130 students, a bus holds 40. How many buses? */
int students = 130, busSize = 40;
printf("\nBuses needed for %d students = %.0f\n",
students, ceil((double)students / busSize));
return 0;
}
Output
sqrt(49) = 7.0 pow(2, 3) = 8.0 abs(-5) = 5 fabs(-2.5) = 2.5 ceil(4.2) = 5.0 floor(9.8) = 9.0 Buses needed for 130 students = 4
6. Recursion: a function calling itself
Recursion means a function calls itself with a smaller problem. Every recursive function needs two things:
- Base case: when to STOP (the tiniest doll). Without it, the program crashes ("stack overflow").
- Recursive case: call yourself with a smaller value.
fact(5) = 5 * fact(4)
fact(4) = 4 * fact(3)
fact(3) = 3 * fact(2)
fact(2) = 2 * fact(1)
fact(1) = 1 โ base case
Going back up: 2*1=2 โ 3*2=6 โ 4*6=24 โ 5*24=120
n =
| Recursion | Loop (iteration) |
|---|---|
| Function calls itself | Uses for/while |
| Short, neat code | Code can be longer |
| Uses more memory (stack) | Uses less memory |
| Needs a base case | Needs a stopping condition |
File: 06_recursion_factorial.c
/*
* Program 6: Recursion - Factorial
* --------------------------------
* Real-life story: Russian dolls (a doll inside a doll inside a doll...).
* You keep opening dolls until you reach the tiniest one. Then you stop.
*
* RECURSION = a function that calls ITSELF.
* It needs:
* 1. a BASE CASE (the tiniest doll) -> stop calling
* 2. a smaller problem each time
*
* 5! = 5 x 4 x 3 x 2 x 1 = 120
* fact(5) = 5 * fact(4)
* fact(4) = 4 * fact(3) ... down to fact(1) = 1
*/
#include <stdio.h>
int fact(int n) {
printf(" calling fact(%d)\n", n);
if (n <= 1) { /* BASE CASE: tiniest doll */
printf(" fact(%d) returns 1 (base case, start going back)\n", n);
return 1;
}
int answer = n * fact(n - 1); /* open the next smaller doll */
printf(" fact(%d) returns %d\n", n, answer);
return answer;
}
int main() {
int n = 5;
int result = fact(n);
printf("\n%d! = %d\n", n, result);
return 0;
}
Output
calling fact(5) calling fact(4) calling fact(3) calling fact(2) calling fact(1) fact(1) returns 1 (base case, start going back) fact(2) returns 2 fact(3) returns 6 fact(4) returns 24 fact(5) returns 120 5! = 120
7. Recursion: Fibonacci
fib(n) = 0 if n == 0
= 1 if n == 1
= fib(n-1) + fib(n-2) otherwise
fib(4)
/ \
fib(3) fib(2)
/ \ / \
fib(2) fib(1) fib(1) fib(0)
/ \
fib(1) fib(0)
n =
File: 07_recursion_fibonacci.c
/*
* Program 7: Recursion - Fibonacci
* --------------------------------
* Real-life story: Rabbits! Every new number = the two numbers before it added.
* 0, 1, 1, 2, 3, 5, 8, 13, ...
*
* fib(0) = 0 (base case)
* fib(1) = 1 (base case)
* fib(n) = fib(n-1) + fib(n-2)
*/
#include <stdio.h>
int fib(int n) {
if (n == 0) return 0; /* base case 1 */
if (n == 1) return 1; /* base case 2 */
return fib(n - 1) + fib(n - 2);/* call myself twice */
}
int main() {
int i;
printf("First 10 Fibonacci numbers:\n");
for (i = 0; i < 10; i++) {
printf("%d ", fib(i));
}
printf("\n");
return 0;
}
Output
First 10 Fibonacci numbers: 0 1 1 2 3 5 8 13 21 34
8. Binary search using recursion
- Find
mid = (low + high) / 2. - If
a[mid] == keyโ found! (base case) - If
key < a[mid]โ search the left half:binarySearch(a, low, mid-1, key) - Else โ search the right half:
binarySearch(a, mid+1, high, key) - If
low > highโ not found (base case)
Find:
File: 08_recursive_binary_search.c
/*
* Program 8: Binary Search using Recursion
* ----------------------------------------
* Real-life story: Finding a word in a dictionary.
* You don't read every page! You open the MIDDLE.
* - Word is before the middle? Look only in the LEFT half.
* - Word is after? Look only in the RIGHT half.
* Each time, half the book disappears. Very fast!
*
* RULE: the array must be SORTED first.
*/
#include <stdio.h>
int binarySearch(int a[], int low, int high, int key) {
if (low > high) { /* BASE CASE: nothing left to search */
return -1;
}
int mid = (low + high) / 2;
printf(" looking between index %d and %d, middle a[%d] = %d\n", low, high, mid, a[mid]);
if (a[mid] == key) { /* BASE CASE: found it */
return mid;
} else if (key < a[mid]) { /* go LEFT */
return binarySearch(a, low, mid - 1, key);
} else { /* go RIGHT */
return binarySearch(a, mid + 1, high, key);
}
}
int main() {
int marks[] = {10, 22, 35, 47, 58, 63, 79, 88, 94}; /* sorted */
int n = 9;
int key = 63;
printf("Searching for %d:\n", key);
int pos = binarySearch(marks, 0, n - 1, key);
if (pos != -1) printf("Found %d at index %d\n\n", key, pos);
else printf("%d not found\n\n", key);
key = 40;
printf("Searching for %d:\n", key);
pos = binarySearch(marks, 0, n - 1, key);
if (pos != -1) printf("Found %d at index %d\n", key, pos);
else printf("%d not found\n", key);
return 0;
}
Output
Searching for 63: looking between index 0 and 8, middle a[4] = 58 looking between index 5 and 8, middle a[6] = 79 looking between index 5 and 5, middle a[5] = 63 Found 63 at index 5 Searching for 40: looking between index 0 and 8, middle a[4] = 58 looking between index 0 and 3, middle a[1] = 22 looking between index 2 and 3, middle a[2] = 35 looking between index 3 and 3, middle a[3] = 47 40 not found
9. Pointers: & and *
Every variable lives in memory at an address. A pointer is a variable that stores an address.
| Write | Read it as | Meaning |
|---|---|---|
int *p; | "p is a pointer to int" | Declare a pointer |
&x | "address of x" | Address operator |
p = &x; | "p points to x" | Store the address |
*p | "value at p" | Dereference (indirection) operator: go to the address and look |
*p = 25; | "put 25 at p" | Changes x! |
%p (like 0x16f355fb8) change every time you run the program. The output below is from one run, and yours will be different. That's normal.*p before giving p an address. Such a "wild pointer" points to random memory. Use int *p = NULL; if you have nothing to point to yet.datatype *name;. Operators: & (address of), * (value at address). Advantages: pass by reference, dynamic memory, efficient arrays/strings, data structures like linked lists.File: 09_pointer_basics.c
/*
* Program 9: Pointers - & and *
* -----------------------------
* Real-life story: Your house and its address.
* - The house holds people (the VALUE).
* - The address tells WHERE the house is ("12, Rose Street").
* - A POINTER is a paper with the address written on it.
*
* &x -> "address of x" (where does x live?)
* *p -> "value at address p" (go to that house and look inside)
*
* NOTE: the addresses printed with %p change every time you run the program.
*/
#include <stdio.h>
int main() {
int candies = 10; /* a house holding 10 */
int *p; /* p is a pointer: it can hold the address of an int */
p = &candies; /* write candies' address on the paper p */
printf("candies = %d\n", candies);
printf("&candies (address)= %p\n", (void *)&candies);
printf("p (same address) = %p\n", (void *)p);
printf("*p (value there) = %d\n", *p);
*p = 25; /* go to the address and change what's inside */
printf("\nAfter *p = 25, candies = %d (changed through the pointer!)\n", candies);
/* pointer to pointer: a paper that has the address of another paper */
int **pp = &p;
printf("**pp = %d\n", **pp);
printf("\nSize of an int pointer on this computer = %lu bytes\n", (unsigned long)sizeof(p));
return 0;
}
Output (addresses will differ on your computer)
candies = 10 &candies (address)= 0x16ee89fe8 p (same address) = 0x16ee89fe8 *p (value there) = 10 After *p = 25, candies = 25 (changed through the pointer!) **pp = 25 Size of an int pointer on this computer = 8 bytes
10. Pointer arithmetic
p + 1 moves to the next element, which is sizeof(type) bytes ahead.
| Operation | Allowed? | Meaning |
|---|---|---|
p++, p-- | โ | Next / previous element |
p + n, p - n | โ | Jump n elements |
q - p | โ | How many elements apart (same array) |
p < q, p == q | โ | Compare positions |
p + q, p * 2, p / 2 | โ | Meaningless, so not allowed |
File: 10_pointer_arithmetic.c
/*
* Program 10: Pointer Arithmetic
* ------------------------------
* Real-life story: Houses on a street, all the same size.
* If one house is 4 steps wide, then "next house" = 4 steps ahead.
*
* p + 1 does NOT add 1 byte. It jumps to the NEXT ELEMENT.
* int is 4 bytes -> p + 1 moves 4 bytes
* char is 1 byte -> p + 1 moves 1 byte
* double is 8 bytes-> p + 1 moves 8 bytes
*
* Allowed: p++, p--, p + n, p - n, p2 - p1 (gap between), compare p1 < p2
* NOT allowed: p1 + p2, p * 2, p / 2
*/
#include <stdio.h>
int main() {
int street[5] = {100, 200, 300, 400, 500};
int *p = &street[0]; /* stand at house 0 */
int *q = &street[4]; /* friend stands at house 4 */
printf("*p = %d (house 0)\n", *p);
p++; /* walk to next house */
printf("after p++, *p = %d (house 1)\n", *p);
p = p + 2; /* jump 2 houses */
printf("after p+2, *p = %d (house 3)\n", *p);
p--; /* step back */
printf("after p--, *p = %d (house 2)\n", *p);
printf("\nGap q - p = %ld houses\n", (long)(q - p));
printf("Is p before q? %s\n", (p < q) ? "yes" : "no");
/* how many BYTES does +1 move? */
char c[2];
double d[2];
printf("\nint : +1 moves %ld bytes\n", (long)((char *)(street + 1) - (char *)street));
printf("char : +1 moves %ld byte\n", (long)((char *)(c + 1) - (char *)c));
printf("double : +1 moves %ld bytes\n", (long)((char *)(d + 1) - (char *)d));
return 0;
}
Output
*p = 100 (house 0) after p++, *p = 200 (house 1) after p+2, *p = 400 (house 3) after p--, *p = 300 (house 2) Gap q - p = 2 houses Is p before q? yes int : +1 moves 4 bytes char : +1 moves 1 byte double : +1 moves 8 bytes
11. Arrays and pointers
| These are the same |
|---|
a = &a[0] |
a[i] = *(a + i) = *(p + i) = p[i] |
&a[i] = a + i |
p++ but NOT a++. The array name is a fixed (constant) address.i =
File: 11_arrays_and_pointers.c
/*
* Program 11: Arrays and Pointers
* -------------------------------
* Real-life story: A train with coaches.
* The NAME of the array is like the engine: it points to coach 0.
*
* a == &a[0] (array name = address of first element)
* a[i] == *(a + i) (coach i = go i steps from the engine and look inside)
* &a[i] == a + i
*/
#include <stdio.h>
int main() {
int a[5] = {5, 10, 15, 20, 25};
int *p = a; /* same as p = &a[0] */
int i, sum = 0;
printf("i a[i] *(a+i) *(p+i) p[i]\n");
for (i = 0; i < 5; i++) {
printf("%d %3d %3d %3d %3d\n", i, a[i], *(a + i), *(p + i), p[i]);
}
/* walk the train with the pointer only */
for (p = a; p < a + 5; p++) {
sum = sum + *p;
}
printf("\nSum using a moving pointer = %d\n", sum);
printf("a == &a[0]? %s\n", (a == &a[0]) ? "yes" : "no");
return 0;
}
Output
i a[i] *(a+i) *(p+i) p[i] 0 5 5 5 5 1 10 10 10 10 2 15 15 15 15 3 20 20 20 20 4 25 25 25 25 Sum using a moving pointer = 75 a == &a[0]? yes
12. Array of pointers
names[0] โโโบ "Anu" names[1] โโโบ "Bala" names[2] โโโบ "Chitra" names[3] โโโบ "Dev"
char names[4][10] (2D array) | char *names[4] (array of pointers) | |
|---|---|---|
| Memory | Every row is 10 chars, even "Dev" | Each name uses only what it needs |
| Swap two names | Copy all the letters | Just swap two arrows |
int *p[3] (array of 3 pointers) with int (*p)[3] (one pointer to an array of 3 ints).File: 12_array_of_pointers.c
/*
* Program 12: Array of Pointers
* -----------------------------
* Real-life story: A class attendance list.
* Names are different lengths. Instead of giving every name a big
* fixed box, we keep a list of POINTERS, each pointing to one name.
*
* char *names[4] -> 4 pointers, each points to a string
* int *ptr[3] -> 3 pointers, each points to an int
*/
#include <stdio.h>
int main() {
char *names[4] = {"Anu", "Bala", "Chitra", "Dev"};
int i;
printf("Attendance list:\n");
for (i = 0; i < 4; i++) {
printf("%d. %s (first letter %c)\n", i + 1, names[i], *names[i]);
}
/* swapping two pointers swaps the order WITHOUT copying the names */
char *temp = names[0];
names[0] = names[3];
names[3] = temp;
printf("\nAfter swapping first and last pointer: %s ... %s\n", names[0], names[3]);
/* array of int pointers */
int x = 7, y = 8, z = 9;
int *ptr[3] = {&x, &y, &z};
printf("\nValues through int pointers: ");
for (i = 0; i < 3; i++) {
printf("%d ", *ptr[i]);
}
printf("\n");
return 0;
}
Output
Attendance list: 1. Anu (first letter A) 2. Bala (first letter B) 3. Chitra (first letter C) 4. Dev (first letter D) After swapping first and last pointer: Dev ... Anu Values through int pointers: 7 8 9
13. Pass by value vs pass by reference
x = y =
| Pass by value | Pass by reference | |
|---|---|---|
| What is sent | A copy of the value | The address (&x) |
| Parameter | int a | int *a |
| Changes original? | No | Yes |
| Example call | swap(x, y) | swap(&x, &y) |
File: 13_pass_by_value_reference.c
/*
* Program 13: Pass by Value vs Pass by Reference
* ----------------------------------------------
* Real-life story: Your homework notebook.
* PASS BY VALUE = you give your friend a PHOTOCOPY.
* Friend scribbles on it -> your notebook is safe.
* PASS BY REFERENCE = you give your friend your HOME ADDRESS.
* Friend comes and writes in your real notebook -> it changes!
*
* In C, "pass by reference" is done by passing ADDRESSES (pointers).
*/
#include <stdio.h>
void swapByValue(int a, int b) { /* gets photocopies */
int temp = a;
a = b;
b = temp;
printf(" inside swapByValue: a = %d, b = %d\n", a, b);
}
void swapByReference(int *a, int *b) { /* gets addresses */
int temp = *a;
*a = *b;
*b = temp;
printf(" inside swapByReference: *a = %d, *b = %d\n", *a, *b);
}
int main() {
int x = 10, y = 20;
printf("Start: x = %d, y = %d\n", x, y);
swapByValue(x, y);
printf("After swapByValue: x = %d, y = %d (NOT swapped)\n\n", x, y);
swapByReference(&x, &y);
printf("After swapByReference: x = %d, y = %d (swapped!)\n", x, y);
return 0;
}
Output
Start: x = 10, y = 20 inside swapByValue: a = 20, b = 10 After swapByValue: x = 10, y = 20 (NOT swapped) inside swapByReference: *a = 20, *b = 10 After swapByReference: x = 20, y = 10 (swapped!)
๐ 2-mark questions and answers
What is a function?
A self-contained block of code that does a specific task. It can take inputs (arguments) and return one value. Example:int add(int a, int b).What is a function prototype? Why is it needed?
A declaration giving the return type, name and parameter types, ending with a semicolon:int add(int, int);. It tells the compiler about the function before it is used, so calls can be checked.Difference between actual and formal parameters?
Actual parameters are the values passed in the call (add(3, 2)). Formal parameters are the variables in the definition that receive them (int a, int b).What is recursion? Give an example.
A function calling itself, with a base case to stop. Example:fact(n) = n * fact(n-1), with fact(1) = 1.What is a base case?
The condition where a recursive function stops calling itself and returns directly. Without it you get infinite recursion and a stack overflow.What is a pointer?
A variable that stores the memory address of another variable.int *p = &x;What are the & and * operators?
& is the address-of operator and gives a variable's address. * is the indirection (dereference) operator and gives the value stored at an address.What is a NULL pointer?
A pointer that points to nothing:int *p = NULL;. It's a safe starting value, so you can check if (p == NULL).What is pointer arithmetic? If int *p = 1000, what is p+1?
Adding/subtracting integers to pointers moves by whole elements. p+1 = 1000 + sizeof(int) = 1004.Why is a[i] the same as *(a+i)?
The array name is the address of the first element. Adding i moves i elements ahead, and * reads the value there.Difference between call by value and call by reference?
Call by value passes a copy, so the original is not changed. Call by reference passes the address, so the function can change the original.Why must we use -lm for math.h?
Math functions are in a separate library (libm).-lm tells the linker to include it.What does strcmp return?
0 if both strings are equal, a negative value if the first comes before the second (by ASCII), and a positive value otherwise.๐ Mini quiz
๐ฏ Practice homework
- Write a function
int isEven(int n)that returns 1 if n is even, else 0. Call it for 1 to 10. - Write a function
float area(float r)that returns the area of a circle (3.14 ร r ร r). - Write a recursive function to find the sum of digits of 4721 (answer 14).
- Write a recursive function
power(base, exp). Test power(2, 10) = 1024. - Use a pointer to find the biggest number in
{4, 19, 7, 3, 12}without usinga[i]. - Write
void doubleIt(int *n)that doubles the original variable. - Write your own
myStrlen(char *s)using only pointer arithmetic. - Sort the attendance list (array of pointers) alphabetically using strcmp and pointer swaps.