Revision Notes C Programming
Keywords, Identifiers, and Data Types
Keywords: Reserved words (e.g., int , return ) that cannot be used as variable names.
Identifiers: Names for variables and functions. Must start with a letter or underscore.
Data Types: Define the type and size of data a variable holds. Qualifiers like unsigned
i n
and long modify them.
.
The following example defines variables with different data types and uses the sizeof
p
operator.
e
#include <stdio.h>
int main() {
Pr
// A valid identifier `student_age` of type `int`
A
int student_age = 20;
C
// `unsigned` qualifier ensures the value is non-negative
unsigned int positive_count = 100;
decimals
J E
// `char` for single characters, `double` for high-precision
char grade = 'A';
double pi = 3.1415926535;
printf("Student's age is %d.\n", student_age);
printf("Grade: %c\n", grade);
printf("Positive Count: %u\n", positive_count);
// Using sizeof operator to see memory allocation
printf("Size of a double is %zu bytes.\n", sizeof(pi));
return 0;
}
Input/Output and Format Specifiers
The standard functions printf() and scanf() use format specifiers to handle different
data types for console I/O.
Data Type Format Specifier
int %d , %i
char %c
float %f
i n
double %lf
.
unsigned int %u
p
string (char array) %s
re
This program prompts the user for their name and age and then prints the input back.
P
#include <stdio.h>
A
int main() {
C
char name[50];
int age;
J E
printf("Enter your first name: ");
scanf("%s", name);
printf("Enter your age: ");
scanf("%d", &age);
printf("\n--- User Profile ---\n");
printf("Name: %s\n", name);
printf("Age: %d years\n", age);
return 0;
}
Operators and Expressions
Operators perform operations on data. Understanding their precedence and side effects is
critical.
Operator Type Examples Description
Arithmetic + , - , * , / , % , ++ , -- Perform mathematical operations.
Relational == , != , >, <, >= , <= Compare two values.
Logical && , || , ! Combine or invert boolean values.
Ternary ?: A compact conditional expression.
Increment/Decrement ( ++ , -- ): Using them multiple times on the same variable in one
expression often leads to Undefined Behavior (UB).
n
Ternary Operator ( ? : ): A compact if-else statement, useful for conditional
i
assignments.
.
This example demonstrates tricky cases of operator behavior, including undefined behavior
p
with increments and a nested ternary operator.
re
#include <stdio.h>
P
int main() {
// --- Tricky Pre/Post-Increment (Potential Exam Question) ---
A
int i = 5;
// The following line is UNDEFINED BEHAVIOR. The output is
C
unpredictable.
E
printf("Undefined Behavior Example: i=%d, i++=%d\n", i, i++);
J
int a = 5;
int b = ++a * 2; // a becomes 6, then 6 * 2 = 12
int c = a++ * 2; // 6 * 2 = 12, then a becomes 7
printf("Pre-increment: b = %d, a = %d\n", b, a);
printf("Post-increment: c = %d, a = %d\n\n", c, a);
// --- Nested Ternary Operator (Potential Exam Question) ---
int score = 75;
char final_grade = (score > 90) ? 'A' : (score > 70) ? 'C' : 'D';
printf("Nested Ternary: A score of %d gets grade '%c'.\n", score,
final_grade);
return 0;
}
Control Flow: Loops and Branches
break exits a loop entirely, while continue skips to the next iteration. This example uses
both within a `for` loop.
#include <stdio.h>
int main() {
printf("--- Loop Demonstration ---\n");
for (int i = 1; i <= 10; i++) {
if (i % 2 == 0) { // If the number is even...
n
continue; // ...skip the rest of this iteration.
i
}
.
if (i > 7) { // If the number is greater than 7...
p
break; // ...exit the loop entirely.
}
e
printf("Processing odd number: %d\n", i);
r
}
return 0;
P
}
Storage Classes
CA
auto
J E
Storage classes determine a variable's scope, lifetime, and storage location.
Storage Class Storage
Stack
Scope
Block
Lifetime
End of block
register CPU Register Block End of block
static Data Segment Block/File Entire program
extern Data Segment Global Entire program
The static keyword makes a local variable persist its value between function calls.
extern declares a variable defined in another file.
#include <stdio.h>
void counter_function() {
// This `static` variable is initialized only once and keeps its
value.
static int call_count = 0;
call_count++;
printf("This function has been called %d time(s).\n", call_count);
}
int main() {
counter_function();
counter_function();
return 0;
}
n
Pointers, Scope, and Memory Management
. i
Scope: A variable is only accessible within the block ( {...} ) where it is defined.
p
const Keyword: Declares a variable as read-only. Modifying it is a compile-time error.
e
Dangling Pointer: A pointer to a memory location that is no longer valid. Accessing it is
r
Undefined Behavior.
P
This code shows a compile error for modifying a const variable and demonstrates how
A
returning the address of a local variable creates a dangling pointer.
C
#include <stdio.h>
E
int* create_dangling_pointer() {
J
int local_variable = 123;
// DANGER: Returning the address of a local variable which will be
destroyed on exit.
return &local_variable;
}
int main() {
// --- `const` and Pointers (Potential Exam Question) ---
const int read_only_var = 100;
// read_only_var = 101; // COMPILE ERROR: Cannot modify a const
variable.
printf("The `const` variable is: %d\n\n", read_only_var);
// --- Dangling Pointer Example (Potential Exam Question) ---
int* dangling_ptr = create_dangling_pointer();
// Dereferencing this pointer is UNDEFINED BEHAVIOR.
printf("Value from dangling pointer: %d ( unpredictable! )\n",
*dangling_ptr);
return 0;
}
Arrays and Strings
An array is a fixed-size collection of elements. A string is a `char` array terminated by a null
character (`\0`).
#include <stdio.h>
#include <string.h> // For string library functions
i n
int main() {
.
int grades[5] = {85, 90, 78, 92, 88};
p
char message[50] = "Hello, ";
e
printf("The second grade is: %d\n", grades[1]);
Pr
strcat(message, "World!"); // Concatenate "World!" to message
printf("Message: %s\n", message);
printf("Length of message: %zu\n", strlen(message));
}
return 0;
CA
J E
Structures and Unions
Structure ( struct ): Groups variables, each with its own memory.
Union ( union ): Groups variables, but all members share the same memory location.
This example highlights the memory difference between a struct and a union, showing how
a union's members overwrite each other.
#include <stdio.h>
typedef struct { int id; float value; } MyStruct;
typedef union { int id; float value; } MyUnion;
int main() {
MyStruct s;
[Link] = 10; [Link] = 25.5;
printf("Struct: id=%d, value=%.1f (Size: %zu bytes)\n\n", [Link],
[Link], sizeof(s));
MyUnion u;
[Link] = 10;
printf("Union after id set: id=%d\n", [Link]);
[Link] = 25.5; // This overwrites the memory used by id
printf("Union after value set: value=%.1f, id=%d (corrupted)\n",
[Link], [Link]);
printf("Size of MyUnion: %zu bytes\n", sizeof(u));
return 0;
}
Pre-processor Directives
. i n
#define
e p
creates a macro, which is a simple text replacement. Passing an argument with
r
side effects (like b++ ) can cause it to be evaluated multiple times, leading to bugs.
P
#include <stdio.h>
A
// A macro vulnerable to side effects
#define CUBE(x) ((x) * (x) * (x))
E
int main() {
int b = 3;
C
J
// --- Side Effect Pitfall (Potential Exam Question) ---
// The macro expands to: ((b++) * (b++) * (b++))
// This is UNDEFINED BEHAVIOR.
int cube_result = CUBE(b++);
printf("CUBE(b++) result is unpredictable: %d\n", cube_result);
printf("Value of b after macro: %d\n", b); // b will be 6
return 0;
}
Command-Line Arguments
Arguments can be passed to a program from the command line and are accessed via argc
(argument count) and argv (argument vector) in `main`.
#include <stdio.h>
int main(int argc, char *argv[]) {
printf("Number of arguments: %d\n", argc);
printf("Program name: %s\n", argv[0]);
for (int i = 1; i < argc; i++) {
printf("Argument %d: %s\n", i, argv[i]);
}
// To run: ./[Link] hello 123
return 0;
}
File Handling
. i n
p
C provides functions in <stdio.h> to perform I/O on files.
Mode Description
re
P
"r" Read: Opens an existing file for reading.
Write: Creates a file for writing. Overwrites existing content.
A
"w"
"a" Append: Opens a file for writing at the end.
C
"r+" Read/Write: Opens an existing file for reading and writing.
J E
This program writes a line to
#include <stdio.h>
[Link] and then reads it back.
int main() {
FILE *fptr;
// --- Writing to a file ---
fptr = fopen("[Link]", "w");
if (fptr == NULL) return 1; // Error check
fprintf(fptr, "User logged in with ID 123.\n");
fclose(fptr);
// --- Reading from the file ---
char line_buffer[100];
fptr = fopen("[Link]", "r");
if (fptr == NULL) return 1;
fscanf(fptr, "%[^\n]", line_buffer); // Read the whole line
printf("Read from file: %s\n", line_buffer);
fclose(fptr);
return 0;
}
. i n
e p
Pr
CA
J E