3 * 25 and 100 - 75. Each of those little maths sentences is an expression.How a C program listens, thinks, decides and repeats
Think of a program as a robot shopkeeper:
scanf, getchar, fgets)total = a + b;)if, else, switch)for, while, do-while)printf, puts, putchar)Every program here is in this folder. To run one: gcc 05_if_and_if_else.c -o prog and then ./prog
3 * 25 and 100 - 75. Each of those little maths sentences is an expression.An expression is a mix of values (operands) and signs (operators) that gives one answer.
| Kind | Example | Answer |
|---|---|---|
| Arithmetic | 3 * 25 | 75 |
| Relational (compare) | 75 < 100 | 1 (true) |
| Logical | hungry && hasMoney | 1 if both are true |
| Assignment | total = 75 | puts 75 in total |
| Conditional | a > b ? a : b | the bigger one |
5 + 1.5 โ 6.5 (int became float)(type).(float)7 / 2 โ 3.5(int)36.9 โ 36 (cut off, not rounded)(type) expression, e.g. (float)a/b.File: 01_expressions_type_conversion.c
/*
* Program 1: Expressions and Type Conversion
* ------------------------------------------
* Real-life story: You buy 3 ice creams at Rs 25 each and pay with Rs 100.
* An EXPRESSION is a little maths sentence the computer solves,
* like 3 * 25 or 100 - total.
*
* Type conversion = changing one kind of number into another.
* Implicit (automatic): C changes it by itself (int + float -> float)
* Explicit (casting) : YOU tell C to change it (float) a
*/
#include <stdio.h>
int main() {
int iceCreams = 3;
int price = 25;
int paid = 100;
/* Arithmetic expression */
int total = iceCreams * price; /* 3 * 25 = 75 */
int change = paid - total; /* 100 - 75 = 25 */
printf("Total = %d, Change = %d\n", total, change);
/* Relational expression: answer is 1 (true) or 0 (false) */
printf("Is total less than paid? %d\n", total < paid);
/* Logical expression: && means AND, || means OR, ! means NOT */
int hungry = 1, hasMoney = 1;
printf("Can I buy food? %d\n", hungry && hasMoney);
/* Precedence: * happens before +, just like in school maths */
printf("2 + 3 * 4 = %d\n", 2 + 3 * 4); /* 14, not 20 */
printf("(2 + 3) * 4 = %d\n", (2 + 3) * 4); /* brackets go first: 20 */
/* Implicit conversion: int + float becomes float automatically */
int apples = 5;
float weight = 1.5;
float mixed = apples + weight;
printf("\nImplicit: 5 + 1.5 = %.1f\n", mixed);
/* Problem: int / int throws away the decimal part */
int marks = 7, subjects = 2;
printf("Without cast: 7 / 2 = %d\n", marks / subjects);
/* Explicit conversion (casting): turn marks into float first */
printf("With cast : 7 / 2 = %.2f\n", (float)marks / subjects);
/* float to int cuts off the decimal part (it does NOT round) */
float temperature = 36.9;
printf("(int)36.9 = %d\n", (int)temperature);
/* char is secretly a number (ASCII) */
char letter = 'A';
printf("'A' as a number = %d, 'A' + 1 = %c\n", letter, letter + 1);
return 0;
}
Output
Total = 75, Change = 25 Is total less than paid? 1 Can I buy food? 1 2 + 3 * 4 = 14 (2 + 3) * 4 = 20 Implicit: 5 + 1.5 = 6.5 Without cast: 7 / 2 = 3 With cast : 7 / 2 = 3.50 (int)36.9 = 36 'A' as a number = 65, 'A' + 1 = B
printf = print something on the screen. scanf = scan (read) what you type.
Both are formatted I/O functions from <stdio.h>. They use format specifiers as blanks to fill.
| Specifier | Type | Example value |
|---|---|---|
%d or %i | int | 42 |
%f | float | 3.140000 |
%lf | double (in scanf) | 3.14159 |
%c | char | A |
%s | string | Ravi |
%u | unsigned int | 40000 |
%ld | long | 1234567890 |
%x / %o | hex / octal | ff / 377 |
%e | scientific | 3.14e+00 |
%% | a percent sign | % |
scanf you must put & before normal variables (&age). & means "the address of the box", so scanf knows where to put the value. Strings like name don't need &.| Code | Meaning |
|---|---|
\n | new line (press Enter) |
\t | tab (big space) |
\\ | a backslash |
\" | a double quote |
\a | beep sound |
printf("control string", var-list); displays output. scanf("control string", &var-list); reads input. The control string contains format specifiers (%d, %f, %c, %s), and the number of specifiers must match the number of variables. A field width like %8.2f means 8 places in total with 2 after the decimal point.File: 02_printf_scanf.c
/*
* Program 2: printf and scanf (Talking to the user)
* -------------------------------------------------
* Real-life story: A school ID card machine.
* It ASKS your name, age and height (scanf = input)
* and then PRINTS your ID card (printf = output).
*
* Format specifiers = blanks to fill:
* %d int %f float %c char
* %s string %lf double %x hexadecimal
*
* Sample input: Ravi 10 4.5 A
*/
#include <stdio.h>
int main() {
char name[20];
int age;
float height;
char section;
printf("Enter name, age, height and section: ");
scanf("%s %d %f %c", name, &age, &height, §ion);
/* & means "the address of the box" so scanf can put the value inside.
Arrays (like name) don't need & */
printf("\n");
printf("+--------------------------+\n");
printf("| SCHOOL ID CARD |\n");
printf("+--------------------------+\n");
printf("| Name : %-14s |\n", name); /* %-14s = 14 spaces wide, left side */
printf("| Age : %-14d |\n", age);
printf("| Height : %-14.1f |\n", height); /* .1 = only 1 digit after dot */
printf("| Section : %-14c |\n", section);
printf("+--------------------------+\n");
/* Field width tricks */
printf("\nField width demo:\n");
printf("[%5d] number in 5 spaces, right side\n", 42);
printf("[%-5d] number in 5 spaces, left side\n", 42);
printf("[%05d] fill empty spaces with zeros\n", 42);
printf("[%8.2f] 8 wide, 2 after the dot\n", 3.14159);
printf("[%x] 255 in hexadecimal\n", 255);
printf("100%% <- use %%%% to print a percent sign\n");
return 0;
}
You type
Ravi 10 4.5 A
Output
Enter name, age, height and section: +--------------------------+ | SCHOOL ID CARD | +--------------------------+ | Name : Ravi | | Age : 10 | | Height : 4.5 | | Section : A | +--------------------------+ Field width demo: [ 42] number in 5 spaces, right side [42 ] number in 5 spaces, left side [00042] fill empty spaces with zeros [ 3.14] 8 wide, 2 after the dot [ff] 255 in hexadecimal 100% <- use %% to print a percent sign
| Function | Does what | Kind |
|---|---|---|
getchar() | reads ONE character | Unformatted input |
putchar(c) | prints ONE character | Unformatted output |
fgets(str, size, stdin) | reads a whole line, spaces too, safely | Unformatted input |
puts(str) | prints a string plus a new line | Unformatted output |
gets(str) โ | reads a line but can overflow. Removed from C11 | Don't use |
scanf("%s", name) stops at the first space. Typing "Ravi Kumar" gives only "Ravi". Use fgets for full names and sentences.getchar() or scanf(), the Enter key is still waiting in the input. That's why the program calls an extra getchar() to "eat" it.File: 03_getchar_putchar_fgets_puts.c
/*
* Program 3: getchar, putchar, fgets, puts
* ----------------------------------------
* Real-life story: A walkie-talkie.
* getchar() = listen to ONE letter
* putchar() = say ONE letter
* fgets() = listen to a WHOLE sentence (with spaces!)
* puts() = say a whole sentence and go to the next line
*
* Why not gets()? gets() does not know how big your box is.
* If someone types too much, it overflows (spills) and breaks things.
* It was REMOVED from C. Always use fgets() instead.
*
* Sample input:
* y
* I love C programming
*/
#include <stdio.h>
int main() {
char answer;
char sentence[50];
printf("Do you like ice cream? (y/n): ");
answer = getchar(); /* reads one character */
getchar(); /* eats the Enter key left behind */
printf("You pressed: ");
putchar(answer); /* prints one character */
putchar('\n');
printf("Type a sentence: ");
fgets(sentence, sizeof(sentence), stdin); /* reads the whole line, safely */
printf("You said: ");
puts(sentence); /* puts adds its own new line.
fgets also keeps your Enter key,
so you see one empty line after it */
/* puts with a fixed message */
puts("Over and out!");
return 0;
}
You type
y I love C programming
Output
Do you like ice cream? (y/n): You pressed: y Type a sentence: You said: I love C programming Over and out!
In C, = does not mean "is equal to". It means "put the right side into the box on the left".
To compare two things, use ==.
| Short way | Long way | score was 10, now it is |
|---|---|---|
score += 5 | score = score + 5 | 15 |
score -= 3 | score = score - 3 | 7 |
score *= 2 | score = score * 2 | 20 |
score /= 4 | score = score / 4 | 2 |
score %= 4 | score = score % 4 | 2 |
y = x++ gives y the old value, then adds 1 ("use, then add"). y = ++x adds 1 first, then gives it to y ("add, then use").variable = expression;. Kinds: simple (=), compound (+= -= *= /= %=), multiple (a = b = c = 0;, evaluated right to left), and increment/decrement (++ --, prefix and postfix).File: 04_assignment_statements.c
/*
* Program 4: Assignment Statements
* --------------------------------
* Real-life story: Your game score.
* = means "PUT this value in the box" (it does NOT mean "equals" like maths).
*
* score = 10; put 10 in score
* score += 5; same as score = score + 5
* score -= 3; same as score = score - 3
* score *= 2; same as score = score * 2
* score /= 4; same as score = score / 4
* score %= 4; same as score = score % 4
*/
#include <stdio.h>
int main() {
int score;
score = 10; /* simple assignment */
printf("Start : %d\n", score);
score += 5; /* found a coin */
printf("score += 5 : %d\n", score);
score -= 3; /* hit by a monster */
printf("score -= 3 : %d\n", score);
score *= 2; /* double-points power-up */
printf("score *= 2 : %d\n", score);
score /= 4; /* shared with 4 teammates */
printf("score /= 4 : %d\n", score);
score %= 4; /* remainder after groups of 4 */
printf("score %%= 4 : %d\n", score);
/* Multiple assignment: right to left, all get the same value */
int a, b, c;
a = b = c = 7;
printf("\na = b = c = 7 -> a=%d b=%d c=%d\n", a, b, c);
/* Increment and decrement */
int lives = 3;
lives++; /* got an extra life: 4 */
printf("lives++ : %d\n", lives);
lives--; /* lost a life: 3 */
printf("lives-- : %d\n", lives);
/* Pre vs Post increment */
int x = 5;
int y = x++; /* y gets OLD x (5), then x becomes 6 */
printf("\ny = x++ -> y=%d, x=%d\n", y, x);
x = 5;
y = ++x; /* x becomes 6 FIRST, then y gets 6 */
printf("y = ++x -> y=%d, x=%d\n", y, x);
return 0;
}
Output
Start : 10 score += 5 : 15 score -= 3 : 12 score *= 2 : 24 score /= 4 : 6 score %= 4 : 2 a = b = c = 7 -> a=7 b=7 c=7 lives++ : 4 lives-- : 3 y = x++ -> y=5, x=6 y = ++x -> y=6, x=6
if (age >= 18) {
printf("Vote!");
}One choice: do it or skip it.if (height >= 120) {
printf("Ride");
} else {
printf("Merry-go-round");
}Two choices: always picks exactly one.| Sign | Means | Sign | Means |
|---|---|---|---|
== | equal to | != | not equal to |
> | greater than | < | less than |
>= | greater or equal | <= | less or equal |
if (x = 5). That puts 5 into x and is always true. To compare, write if (x == 5).cond ? a : b is a short if-else.File: 05_if_and_if_else.c
/*
* Program 5: if and if-else
* -------------------------
* Real-life story: The roller-coaster gate.
* "IF you are at least 120 cm tall, you may ride. ELSE, try the merry-go-round."
*
* if (condition) { -> runs only when condition is true
* ...
* } else { -> runs when condition is false
* ...
* }
*/
#include <stdio.h>
int main() {
int height = 115;
int age = 19;
int number = 7;
/* Simple if: only one choice */
if (age >= 18) {
printf("Age %d: You can vote!\n", age);
}
/* if-else: two choices */
if (height >= 120) {
printf("Height %d cm: Enjoy the roller-coaster!\n", height);
} else {
printf("Height %d cm: Too short, try the merry-go-round.\n", height);
}
/* Even or odd: % 2 gives 0 for even numbers */
if (number % 2 == 0) {
printf("%d is EVEN\n", number);
} else {
printf("%d is ODD\n", number);
}
/* Ternary operator: a tiny if-else on one line
condition ? valueIfTrue : valueIfFalse */
int a = 12, b = 9;
int bigger = (a > b) ? a : b;
printf("Bigger of %d and %d is %d\n", a, b, bigger);
return 0;
}
Output
Age 19: You can vote! Height 115 cm: Too short, try the merry-go-round. 7 is ODD Bigger of 12 and 9 is 12
else runs when none are true. Use it when there are many ranges (grades, slabs, age groups).File: 06_else_if_ladder_grade.c
/*
* Program 6: else-if ladder (Grade calculator)
* --------------------------------------------
* Real-life story: The teacher gives grades.
* The computer climbs down a ladder and stops at the FIRST step that is true.
*
* 90 and above -> O (Outstanding)
* 80 to 89 -> A+
* 70 to 79 -> A
* 60 to 69 -> B
* 50 to 59 -> C
* below 50 -> F (Fail)
*/
#include <stdio.h>
int main() {
int marks[] = {95, 84, 72, 65, 51, 30}; /* six students */
int i;
for (i = 0; i < 6; i++) {
int m = marks[i];
char *grade; /* holds the grade word */
if (m >= 90) {
grade = "O (Outstanding)";
} else if (m >= 80) {
grade = "A+ (Excellent)";
} else if (m >= 70) {
grade = "A (Very good)";
} else if (m >= 60) {
grade = "B (Good)";
} else if (m >= 50) {
grade = "C (Pass)";
} else {
grade = "F (Try again!)";
}
printf("Student %d: %3d marks -> Grade %s\n", i + 1, m, grade);
}
return 0;
}
Output
Student 1: 95 marks -> Grade O (Outstanding) Student 2: 84 marks -> Grade A+ (Excellent) Student 3: 72 marks -> Grade A (Very good) Student 4: 65 marks -> Grade B (Good) Student 5: 51 marks -> Grade C (Pass) Student 6: 30 marks -> Grade F (Try again!)
Nested if = an if inside another if. Like boxes inside boxes ๐ฆ.
File: 07_nested_if_atm_pin.c
/*
* Program 7: Nested if (an if inside an if)
* -----------------------------------------
* Real-life story: Taking money from an ATM.
* Step 1: Is the card inserted?
* Step 2: Is the PIN correct?
* Step 3: Is there enough balance?
* You only check the next step if the previous one was OK.
*/
#include <stdio.h>
int main() {
int cardInserted = 1; /* 1 = yes */
int correctPin = 1234;
int enteredPin = 1234;
int balance = 5000;
int withdraw = 2000;
if (cardInserted == 1) {
printf("Card found.\n");
if (enteredPin == correctPin) {
printf("PIN correct.\n");
if (withdraw <= balance) {
balance = balance - withdraw;
printf("Please collect Rs %d.\n", withdraw);
printf("Balance left: Rs %d\n", balance);
} else {
printf("Not enough balance!\n");
}
} else {
printf("Wrong PIN!\n");
}
} else {
printf("Please insert your card.\n");
}
return 0;
}
Output
Card found. PIN correct. Please collect Rs 2000. Balance left: Rs 3000
| Units | Rate |
|---|---|
| 0 โ 100 | Free |
| 101 โ 200 | Rs 2 per unit |
| 201 โ 500 | Rs 4 per unit |
| Above 500 | Rs 6 per unit |
File: 08_electricity_bill.c
/*
* Program 8: Electricity Bill (else-if ladder with slabs)
* -------------------------------------------------------
* Real-life story: The more electricity you use, the costlier each unit gets.
*
* First 100 units -> Rs 0 (free)
* 101 to 200 units -> Rs 2 per unit
* 201 to 500 units -> Rs 4 per unit
* Above 500 units -> Rs 6 per unit
*/
#include <stdio.h>
int main() {
int homes[] = {80, 150, 350, 620};
int i;
for (i = 0; i < 4; i++) {
int units = homes[i];
int bill;
if (units <= 100) {
bill = 0;
} else if (units <= 200) {
bill = (units - 100) * 2;
} else if (units <= 500) {
bill = 100 * 2 + (units - 200) * 4;
} else {
bill = 100 * 2 + 300 * 4 + (units - 500) * 6;
}
printf("House %d used %3d units -> Bill = Rs %d\n", i + 1, units, bill);
}
return 0;
}
Output
House 1 used 80 units -> Bill = Rs 0 House 2 used 150 units -> Bill = Rs 100 House 3 used 350 units -> Bill = Rs 800 House 4 used 620 units -> Bill = Rs 2120
switch (choice) {
case 1: ...; break; // if choice is 1
case 2: ...; break; // if choice is 2
default: ...; // if nothing matched
}
| switch | else-if ladder | |
|---|---|---|
| Checks | only equal to (==) | any condition (<, >, && ...) |
| Works with | int and char only | any type, including float and ranges |
| Best for | menus, fixed choices | ranges like marks or units |
| Speed | jumps directly | checks one by one |
case constant. On a match, execution starts there and continues until break. default runs if no case matches. Case labels must be unique integer or char constants; float and strings are not allowed.File: 09_switch_atm_menu.c
/*
* Program 9: switch statement (ATM menu)
* --------------------------------------
* Real-life story: An ATM shows buttons 1, 2, 3, 4.
* switch jumps straight to the "case" that matches the button.
* break = "I'm done, leave the switch".
* default = "none of the buttons matched".
*
* Sample input: 1 2 500 3 1000 7 4
*/
#include <stdio.h>
int main() {
int balance = 2000;
int choice, amount;
do {
printf("\n--- ATM MENU ---\n");
printf("1. Check balance\n2. Withdraw\n3. Deposit\n4. Exit\n");
printf("Choose: ");
scanf("%d", &choice);
switch (choice) {
case 1:
printf("Your balance is Rs %d\n", balance);
break;
case 2:
printf("Amount to withdraw: ");
scanf("%d", &amount);
if (amount <= balance) {
balance -= amount;
printf("Collect Rs %d. New balance Rs %d\n", amount, balance);
} else {
printf("Not enough money!\n");
}
break;
case 3:
printf("Amount to deposit: ");
scanf("%d", &amount);
balance += amount;
printf("Deposited. New balance Rs %d\n", balance);
break;
case 4:
printf("Thank you! Bye.\n");
break;
default:
printf("Wrong button! Try again.\n");
}
} while (choice != 4);
return 0;
}
You type
1 2 500 3 1000 7 4
Output
--- ATM MENU --- 1. Check balance 2. Withdraw 3. Deposit 4. Exit Choose: Your balance is Rs 2000 --- ATM MENU --- 1. Check balance 2. Withdraw 3. Deposit 4. Exit Choose: Amount to withdraw: Collect Rs 500. New balance Rs 1500 --- ATM MENU --- 1. Check balance 2. Withdraw 3. Deposit 4. Exit Choose: Amount to deposit: Deposited. New balance Rs 2500 --- ATM MENU --- 1. Check balance 2. Withdraw 3. Deposit 4. Exit Choose: Wrong button! Try again. --- ATM MENU --- 1. Check balance 2. Withdraw 3. Deposit 4. Exit Choose: Thank you! Bye.
Press a button
break, C keeps running the next case too. That's called fall-through. Look at "Forgot break" in the output below.File: 10_switch_fallthrough.c
/*
* Program 10: switch fall-through (Traffic light + vowels)
* --------------------------------------------------------
* Real-life story 1: Traffic light colours.
* Real-life story 2: Checking vowels. Many cases share one answer.
*
* If you FORGET break, C keeps running into the next case.
* This is called FALL-THROUGH. Sometimes it's a bug,
* sometimes we use it on purpose to group cases together.
*/
#include <stdio.h>
int main() {
char lights[] = {'R', 'Y', 'G', 'B'};
int i;
printf("Traffic light:\n");
for (i = 0; i < 4; i++) {
switch (lights[i]) { /* switch works with int and char */
case 'R': printf(" RED -> STOP\n"); break;
case 'Y': printf(" YELLOW -> GET READY\n"); break;
case 'G': printf(" GREEN -> GO\n"); break;
default: printf(" %c? That's not a traffic light colour!\n", lights[i]);
}
}
/* Fall-through on purpose: a, e, i, o, u all reach the same printf */
char word[] = "piano";
printf("\nLetters of \"%s\":\n", word);
for (i = 0; word[i] != '\0'; i++) {
switch (word[i]) {
case 'a':
case 'e':
case 'i':
case 'o':
case 'u':
printf(" %c is a vowel\n", word[i]);
break;
default:
printf(" %c is a consonant\n", word[i]);
}
}
/* Fall-through by mistake: no break after case 1 */
int level = 1;
printf("\nForgot break (level 1):\n");
switch (level) {
case 1: printf(" Level 1 reward\n"); /* no break here! */
/* fall through */
case 2: printf(" Level 2 reward (oops, fell through)\n");
break;
case 3: printf(" Level 3 reward\n");
}
return 0;
}
Output
Traffic light: RED -> STOP YELLOW -> GET READY GREEN -> GO B? That's not a traffic light colour! Letters of "piano": p is a consonant i is a vowel a is a vowel n is a consonant o is a vowel Forgot break (level 1): Level 1 reward Level 2 reward (oops, fell through)
| for | while | do-while | |
|---|---|---|---|
| Use when | you know the count | you don't know the count | it must run at least once |
| Condition checked | before (entry-controlled) | before (entry-controlled) | after (exit-controlled) |
| Minimum runs | 0 | 0 | 1 |
| Semicolon at end? | no | no | yes: while(x); |
File: 11_looping_statements.c
/*
* Program 11: Looping statements (for, while, do-while)
* -----------------------------------------------------
* Real-life story: A traffic light changes again and again.
* for -> when you KNOW how many times (3 rounds of the light)
* while -> when you DON'T know how many times (wait until the bus comes)
* do-while -> do it at least ONCE, then check (ring the doorbell, then wait)
*/
#include <stdio.h>
int main() {
int round;
/* FOR loop: 3 rounds of the traffic light */
printf("FOR loop - traffic light, 3 rounds:\n");
for (round = 1; round <= 3; round++) {
printf(" Round %d: RED -> YELLOW -> GREEN\n", round);
}
/* WHILE loop: wait for the bus; it arrives at minute 4 */
int minute = 0;
int busArrives = 4;
printf("\nWHILE loop - waiting for the bus:\n");
while (minute < busArrives) {
minute++;
printf(" Minute %d: still waiting...\n", minute);
}
printf(" Bus is here!\n");
/* WHILE loop that runs ZERO times: condition false at the start */
int sweets = 0;
while (sweets > 0) {
printf(" This never prints\n");
}
printf("\nWHILE with 0 sweets ran 0 times.\n");
/* DO-WHILE runs ONCE even though the condition is false */
int rings = 0;
printf("\nDO-WHILE - ring the doorbell:\n");
do {
rings++;
printf(" Ding dong! (ring %d)\n", rings);
} while (rings < 0); /* false, but the body already ran once */
/* Sum of 1 to 10 */
int sum = 0, n;
for (n = 1; n <= 10; n++) {
sum += n;
}
printf("\nSum of 1 to 10 = %d\n", sum);
return 0;
}
Output
FOR loop - traffic light, 3 rounds: Round 1: RED -> YELLOW -> GREEN Round 2: RED -> YELLOW -> GREEN Round 3: RED -> YELLOW -> GREEN WHILE loop - waiting for the bus: Minute 1: still waiting... Minute 2: still waiting... Minute 3: still waiting... Minute 4: still waiting... Bus is here! WHILE with 0 sweets ran 0 times. DO-WHILE - ring the doorbell: Ding dong! (ring 1) Sum of 1 to 10 = 55
| Statement | What it does |
|---|---|
break | leaves the loop (or switch) right away |
continue | skips the rest of this round and goes to the next round |
goto label; | jumps to label: anywhere in the function. Avoid it, because it makes "spaghetti code" |
return | leaves the whole function |
File: 12_break_continue_goto.c
/*
* Program 12: break, continue, goto (jump statements)
* ---------------------------------------------------
* Real-life story: Eating sweets from a box of 10.
* continue -> "skip this one" (sweet number 4 is sour, skip it)
* break -> "stop now" (tummy full at sweet number 8)
* goto -> "jump to a label" (rarely used, makes code messy)
*/
#include <stdio.h>
int main() {
int sweet;
printf("Eating sweets:\n");
for (sweet = 1; sweet <= 10; sweet++) {
if (sweet == 4) {
printf(" Sweet %d is sour, skip it (continue)\n", sweet);
continue; /* jump to the next round of the loop */
}
if (sweet == 8) {
printf(" Sweet %d: tummy full, stop! (break)\n", sweet);
break; /* leave the loop completely */
}
printf(" Ate sweet %d\n", sweet);
}
/* Find the first number divisible by 7 between 50 and 100 */
int n;
for (n = 50; n <= 100; n++) {
if (n % 7 == 0) {
printf("\nFirst multiple of 7 after 50 is %d\n", n);
break;
}
}
/* goto: jump to a label. Shown only so you know it exists. */
int count = 1;
start:
printf("goto round %d\n", count);
count++;
if (count <= 3) {
goto start; /* jump back up to the label "start:" */
}
return 0;
}
Output
Eating sweets: Ate sweet 1 Ate sweet 2 Ate sweet 3 Sweet 4 is sour, skip it (continue) Ate sweet 5 Ate sweet 6 Ate sweet 7 Sweet 8: tummy full, stop! (break) First multiple of 7 after 50 is 56 goto round 1 goto round 2 goto round 3
#include), labels jars (#define) and removes recipes not needed today (#ifdef). That helper is the preprocessor. It works before compiling.| Directive | Kid meaning | Example |
|---|---|---|
#include | bring in another file | #include <stdio.h> |
#define | make a label (a macro) | #define PI 3.14 |
#define with ( ) | a mini-function macro | #define SQUARE(x) ((x)*(x)) |
#undef | remove a label | #undef PI |
#ifdef / #ifndef | include code only if a label is (or isn't) defined | #ifdef DEBUG |
#if #elif #else #endif | if-else, but at preprocessing time | #if VERSION > 2 |
#pragma | special instructions for the compiler | #pragma once |
<stdio.h> with angle brackets searches the system folders. "myfile.h" with quotes searches your own folder first.#define BAD(x) x*x vs #define GOOD(x) ((x)*(x))#, processed before compilation. Types: file inclusion (#include), macro substitution (#define, #undef), conditional compilation (#if, #ifdef, #ifndef, #else, #elif, #endif) and other (#pragma, #error). They do not end with a semicolon.File: 13_preprocessor_directives.c
/*
* Program 13: Preprocessor directives
* -----------------------------------
* Real-life story: Before a cook starts cooking, a helper gets everything ready:
* brings the ingredients (#include), sticks labels on jars (#define),
* and removes recipes we don't need today (#ifdef).
* That helper is the PREPROCESSOR. It works BEFORE the compiler.
* Every directive starts with #.
*/
#include <stdio.h> /* bring in printf, scanf ... */
#define PI 3.14159 /* a constant label: PI means 3.14159 */
#define SCHOOL "Sunshine School"
#define SQUARE(x) ((x) * (x)) /* a macro with an argument */
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define DEBUG /* turn ON debug messages */
int main() {
float radius = 2.0;
printf("School: %s\n", SCHOOL);
printf("Area of circle (r=2) = %.2f\n", PI * radius * radius);
printf("SQUARE(5) = %d\n", SQUARE(5));
printf("SQUARE(2+3) = %d (brackets in the macro keep it right)\n", SQUARE(2 + 3));
printf("MAX(10, 25) = %d\n", MAX(10, 25));
/* Conditional compilation */
#ifdef DEBUG
printf("[DEBUG] This line is included because DEBUG is defined\n");
#endif
#ifndef TEST_MODE
printf("TEST_MODE is NOT defined, so this line is included\n");
#endif
#undef DEBUG /* remove the DEBUG label */
#ifdef DEBUG
printf("This will NOT print\n");
#else
printf("DEBUG was removed with #undef\n");
#endif
/* Built-in macros */
printf("This is line %d of file %s\n", __LINE__, __FILE__);
return 0;
}
Output
School: Sunshine School Area of circle (r=2) = 12.57 SQUARE(5) = 25 SQUARE(2+3) = 25 (brackets in the macro keep it right) MAX(10, 25) = 25 [DEBUG] This line is included because DEBUG is defined TEST_MODE is NOT defined, so this line is included DEBUG was removed with #undef This is line 46 of file 13_preprocessor_directives.c
| Command | Stops after | Makes |
|---|---|---|
gcc -E hello.c -o hello.i | Preprocessing | hello.i (575 lines, because stdio.h was pasted in) |
gcc -S hello.c -o hello.s | Compiling | hello.s (37 lines of assembly) |
gcc -c hello.c -o hello.o | Assembling | hello.o (832 bytes of machine code) |
gcc hello.o -o hello | Linking | hello (33432 bytes, ready to run) |
Here is what each stage actually looked like when we ran it:
End of hello.i: GREETING got replaced and the comments are gone
int main() {
printf("%s\n", "Hello, I went through all 4 steps!");
return 0;
}
Start of hello.s: assembly language
.build_version macos, 26, 0 sdk_version 27, 0
.section __TEXT,__text,regular,pure_instructions
.globl _main ; -- Begin function main
.p2align 2
_main: ; @main
.cfi_startproc
; %bb.0:
sub sp, sp, #32
stp x29, x30, [sp, #16] ; 16-byte Folded Spill
add x29, sp, #16
.cfi_def_cfa w29, 16
.cfi_offset w30, -8
.cfi_offset w29, -16
mov w8, #0 ; =0x0
Start of hello.o: machine code shown in hex
00000000: cffa edfe 0c00 0001 0000 0000 0100 0000 ................
00000010: 0400 0000 b801 0000 0020 0000 0000 0000 ......... ......
00000020: 1900 0000 3801 0000 0000 0000 0000 0000 ....8...........
00000030: 0000 0000 0000 0000 0000 0000 0000 0000 ................
; is a compile error. A spelling mistake like prntf becomes a linker error ("undefined reference"). Dividing by zero happens while running, so it's a runtime error.File: 14_compilation_process.c
/*
* Program 14: The compilation process
* -----------------------------------
* Real-life story: Turning a recipe written in English into a cake.
*
* hello.c --(1. Preprocessor)--> hello.i (#include and #define are pasted in)
* hello.i --(2. Compiler)------> hello.s (assembly language)
* hello.s --(3. Assembler)-----> hello.o (machine code, 0s and 1s)
* hello.o --(4. Linker)--------> hello (joins with printf's code, ready to run)
*
* Try these commands one by one:
* gcc -E 14_compilation_process.c -o hello.i (stop after preprocessing)
* gcc -S 14_compilation_process.c -o hello.s (stop after compiling)
* gcc -c 14_compilation_process.c -o hello.o (stop after assembling)
* gcc hello.o -o hello (link)
* ./hello (run!)
*/
#include <stdio.h>
#define GREETING "Hello, I went through all 4 steps!"
int main() {
printf("%s\n", GREETING);
return 0;
}
Output
Hello, I went through all 4 steps!
= is the assignment operator: it stores a value (a = 5). == is the relational operator: it compares two values and gives 1 or 0 (a == 5).(type). Example: float avg = (float)sum / n;#define SQUARE(x) ((x)*(x))while(1) { } or for(;;) { }scanf and print it in Fahrenheit (F = C * 9 / 5 + 32). Use %.1f.continue).CUBE(x) and a macro IS_EVEN(n). Test them.gcc -E on one of your programs and count how many lines the .i file has.