The C language employs a sequence of characters from the source character set to create executable programs. This guide covers essential components including Linux OS usage, data types, constants and variables, operators, input/output operations, control statements, arrays, pointers, functions, structures, unions, and memory management.
Basic Program Structure
#include<stdio.h>
int main() {
printf("hello world!\n");
return 0;
}
The main function serves as the program's entry point, and return 0 marks its exit.
Performing Simple Calculations
printf("%d\n", 23 + 43);
printf("23+43=%d\n", 23 + 43);
The %d format specifier indicates where an integer value should be inserted in the output.
Standard Library Functions
Library functions provide pre-built routines to simplify coding. Documentation can be found at standard C library references.
The printf() Function
This function outputs text to the console. It does not automatically append a newline character.
Width Specification:
printf("%5d\n", 123); // Outputs: " 123"
printf("%-5d\n", 123); // Outputs: "123 "
printf("%12f\n", 123.456); // Outputs: " 123.456000"
Sign Display:
printf("%+d\n", 12); // Outputs: "+12"
printf("%+d\n", -12); // Outputs: "-12"
Precision Control:
printf("%.3f\n", 0.5); // Outputs: "0.500"
printf("%.3f\n", 0.54321); // Outputs: "0.543"
printf("%8.2f\n", 0.54321); // Outputs: " 0.54"
Partial String Output:
printf("%8.2s\n", "123456789"); // Outputs: " 12"
printf("%-8.2s\n", "123456789"); // Outputs: "12 "
The scanf() Function
This function reads user input from the keyboard. In some compilers like MSVC, a definition may be needed to suppress warnings:
#define _CRT_SECURE_NO_WARNINGS 1
Basic Usage:
int val1, val2;
float num1, num2;
scanf("%d %d %f %f", &val1, &val2, &num1, &num2);
printf("%d %d %f %f", val1, val2, num1, num2);
Return Value:
scanf() returns an integer indicating the number of successfully read items, or EOF on end-of-file.
Placeholders:
%[]: Matches a set of characters.%c: Reads a single character.%s: Reads a string until whitespace.
Assignment Suppression:
The * character can be used to read but discard input matching a specifier.
int yr, mo, dy;
scanf("%d%*c%d%*c%d", &yr, &mo, &dy);
Character I/O Functions
getchar() reads a single character from stdin, while putchar() writes one to stdout.
int ch = getchar();
putchar(ch);
These function are useful for skipping lines, counting characters, or ignoring whitespace.
Blocks and Scope
A block is a compound statement enclosed in braces {}. Scope defines where a variable is accessible.
Block Scope: Variables declared inside a block are local to that block.
{
int localVar = 99;
printf("%d", localVar);
}
// localVar not accessible here
File Scope: Variables declared outside all functions have global scope.
int globalCounter = 7;
void display() {
printf("%d", globalCounter);
}
C Keywords
C reserves 32 keywords for language use. These include storage class specifiers (auto, static, register, extern), type specifiers (char, int, float, etc.), control flow keywords (if, for, while, etc.), and qualifiers (const, volatile).
The sizeof Operator:
This operator returns the size in bytes of a type or expression.
size_t intSize = sizeof(int);
size_t varSize = sizeof(myVar);
Use the %zu format specifier to print size_t values.
Signed and Unsigned Types:
The signed and unsigned keywords modify enteger types to specify whether they represent both positive and negative values, or only non-negative values, respectively.
C Statements
Statements in C can be categorized as:
- Null statements (
;) - Expression statements
- Function call statements
- Compound statements (blocks)
- Control statements (branching, looping, jumps)
Computation Basics
Algorithms define the steps for computation. C programs are typically compiled into machine code. Input is line-oriented, terminated by pressing Enter.
Basic I/O:
int userInput;
double userValue;
scanf("%d", &userInput);
printf("%d\n", userInput);
scanf("%lf", &userValue);
printf("%f", userValue);
Format Specifiers:
Common specifiers include %d for int, %ld for long, %f for float/double, %c for char, %s for strings, %p for pointers, and %x for hexadecimal.
Escape Sequences:
Special characters like \n (newline), \t (tab), \\ (backslash), and \" (double quote) are represented with escape sequences.
Variables and Data Types
A variable is a named memory location for storing data. Identifiers must start with a letter or underscore, followed by letters, digits, or underscores.
Variable Definition and Initialization:
int counter; // Declaration
counter = 0; // Assignment
int index = 0; // Initialization
Fundamental Types:
- Integers:
short,int,long,long long(signed/unsigned variants). - Floating-point:
float,double,long double. - Character:
char(may be signed or unsigned by default). - Boolean:
_Bool(from C99, use<stdbool.h>forbool,true,false).
Expressions and Operators
An expression combines operators and operands to compute a value.
Arithmetic Operators: +, -, *, /, %.
Integer division truncates the fractional part. The modulo operator % works only with integers.
int quotient = 6 / 4; // Result: 1
float result = 6.0 / 4; // Result: 1.5
int remainder = 7 % -5; // Result: 2 (sign follows first operand)
Assignment Operators: =, +=, -=, *=, /=, %=.
Increment/Decrement: ++, -- (prefix and postfix).
int x = 10;
printf("%d", x++); // Prints 10, then x becomes 11
printf("%d", ++x); // x becomes 12, then prints 12
Operator Precedence and Associativity: Operators have defined precedence levels; consult a reference table for details. Parentheses can be used to enforce evaluation order.
Swapping Variables:
int temp = a;
a = b;
b = temp;
Control Flow: Decision Making
Relational Operators: ==, !=, >, >=, <, <= evaluate to 1 (true) or 0 (false).
The if-else Statement:
const int PASS_MARK = 60;
int score;
scanf("%d", &score);
if (score >= PASS_MARK) {
printf("Passed\n");
} else {
printf("Failed\n");
}
Always use braces {} for multi-statement blocks.
Comments:
Use // for single-line comments and /* ... */ for multi-line comments.
Control Flow: Looping
The while Loop:
int num, digitCount = 0;
scanf("%d", &num);
do {
num /= 10;
digitCount++;
} while (num > 0);
printf("Digits: %d\n", digitCount);
The for Loop:
int n, factorial = 1;
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
factorial *= i;
}
printf("%d! = %d\n", n, factorial);
Loop Selection:
- Use
forfor a known number of iterations. - Use
do-whilewhen the body must execute at least once. - Use
whilewhen the iteration count is uncertain.
Advanced Control Flow
Logical Operators: ! (NOT), && (AND), || (OR). Logical expressions short-circuit evaluation.
Conditional Operator: ? :
int absValue = (x >= 0) ? x : -x;
Comma Operator: Evaluates expressions left-to-right, yielding the value of the rightmost expression.
Nested and Cascaded if-else:
if (a > b) {
if (a > c) max = a;
else max = c;
} else {
if (b > c) max = b;
else max = c;
}
The switch Statement:
int choice;
scanf("%d", &choice);
switch (choice) {
case 1: printf("Option 1\n"); break;
case 2: printf("Option 2\n"); break;
default: printf("Invalid\n");
}
Loop Control with break and continue:
break exits the innermost loop; continue skips to the next iteration.
The goto Statement:
for (...) {
for (...) {
if (error) goto cleanup;
}
}
cleanup:
// Cleanup code
Use sparingly as it can harm code readability.
Common Programming Examples
Number Guessing Game:
#include <stdlib.h>
#include <time.h>
int main() {
srand(time(0));
int secret = rand() % 100 + 1;
int guess, attempts = 0;
do {
printf("Guess (1-100): ");
scanf("%d", &guess);
attempts++;
if (guess > secret) printf("Too high\n");
else if (guess < secret) printf("Too low\n");
} while (guess != secret);
printf("Correct! Attempts: %d\n", attempts);
}
Integer Reversal:
int original, reversed = 0;
scanf("%d", &original);
int working = original;
while (working > 0) {
reversed = reversed * 10 + working % 10;
working /= 10;
}
printf("%d reversed is %d\n", original, reversed);
Arrays
An array stores a fixed-size sequential collection of elements of the same type.
Declaration and Initialization:
int scores[100];
int primes[] = {2, 3, 5, 7, 11}; // Size inferred
int zeros[10] = {0}; // All elements zero
Array Traversal:
for (int idx = 0; idx < arrayLength; idx++) {
printf("%d ", arr[idx]);
}
Array indices start at 0. Accessing out-of-bounds indices leads to undefined behavior.
Array Size:
Use sizeof(arr) / sizeof(arr[0]) to compute the number of elements.
Arrays as Function Parameters: When passing an array to a function, it decays to a pointer to its first element.
void processArray(int data[], int len) {
for (int i = 0; i < len; i++) {
// Process data[i]
}
}
// Equivalent prototypes:
// void processArray(int *data, int len);
// void processArray(int [], int);
Two-Dimensional Arrays:
int matrix[3][5];
for (int row = 0; row < 3; row++) {
for (int col = 0; col < 5; col++) {
matrix[row][col] = row * col;
}
}
// Initialization:
int grid[][3] = {{1,2,3}, {4,5,6}};
Functions
Functions encapsulate reusable code segments.
Definition and Call:
int maximum(int x, int y) {
return (x > y) ? x : y;
}
int main() {
int a = 5, b = 8;
int m = maximum(a, b);
printf("Max: %d\n", m);
}
Function Prototype: A declaration that specifies the function's return type, name, and parameter types.
int add(int, int); // Prototype
int main() {
int sum = add(3, 4);
}
int add(int x, int y) { return x + y; } // Definition
Parameter Passing: C uses pass-by-value. To modify an argument, pass its address.
void increment(int *ptr) {
(*ptr)++;
}
int main() {
int val = 10;
increment(&val);
printf("%d\n", val); // Prints 11
}
Local Variables: Variables declared inside a function have automatic storage duration and are not initialized by default.
Algorithms on Arrays
Linear Search:
int findIndex(int key, int arr[], int size) {
for (int i = 0; i < size; i++) {
if (arr[i] == key) return i;
}
return -1;
}
Binary Search (requires sorted array):
int binarySearch(int key, int arr[], int size) {
int low = 0, high = size - 1;
while (low <= high) {
int mid = (low + high) / 2;
if (arr[mid] == key) return mid;
else if (arr[mid] < key) low = mid + 1;
else high = mid - 1;
}
return -1;
}
Selection Sort:
void selectionSort(int arr[], int n) {
for (int i = 0; i < n-1; i++) {
int minIdx = i;
for (int j = i+1; j < n; j++) {
if (arr[j] < arr[minIdx]) minIdx = j;
}
int temp = arr[i];
arr[i] = arr[minIdx];
arr[minIdx] = temp;
}
}
Prime Number Algorithms:
- Trial division up to
n-1. - Skip even numbers after checking 2.
- Trial division up to
sqrt(n). - Sieve of Eratosthenes for generating primes up to a limit.
Pointers
A pointer variable stores a memory address.
Pointer Declaration and Usage:
int value = 42;
int *ptr = &value; // ptr holds address of value
printf("Value: %d\n", *ptr); // Dereference to access value
*ptr = 99; // Modify value via pointer
Pointer Arithmetic:
Adding an integer n to a pointer advances it by n * sizeof(type) bytes.
int arr[] = {10, 20, 30, 40};
int *p = arr;
printf("%d\n", *(p + 1)); // Prints 20
Dynamic Memory Allocation:
#include <stdlib.h>
int *dynamicArray = (int*)malloc(10 * sizeof(int));
if (dynamicArray != NULL) {
// Use the array
free(dynamicArray); // Release memory
}
Pointers and const:
const int *p: Pointer to constant data (data cannot be modified viap).int *const p: Constant pointer (pointer itself cannot point elsewhere).const int *const p: Both are constant.
Strings
In C, strings are null-terminated character arrays ('\0').
String Initialization:
char greeting[] = {"Hello"}; // Array with null terminator
char *msg = "World"; // Pointer to string literal
char buffer[20] = ""; // Empty string
String literals are immutable; use arrays for modifiable strings.
String Input/Output:
char name[50];
printf("Enter name: ");
scanf("%49s", name); // Limit input length
printf("Hello, %s\n", name);
String Functions from <string.h>:
strlen(s): Returns length excluding null terminator.strcmp(s1, s2): Compares strings lexicographically.strcpy(dest, src): Copies string.strcat(dest, src): Concatenates strings.strchr(s, c): Finds first occurrence of characterc.
Safe Alternatives: strncpy, strncat, strncmp allow specifying maximum lengths to prevent buffer overflows.
Implementing String Functions:
int myStrlen(const char *s) {
int len = 0;
while (*s++) len++;
return len;
}
int myStrcmp(const char *s1, const char *s2) {
while (*s1 && (*s1 == *s2)) {
s1++; s2++;
}
return *(unsigned char*)s1 - *(unsigned char*)s2;
}
char* myStrcpy(char *dest, const char *src) {
char *start = dest;
while ((*dest++ = *src++));
return start;
}