This page covers the absolute basics of C programming: fundamental data types, how to declare and use variables and constants, and basic input/output operations. Each section includes explanations, runnable code snippets, and their expected outputs.
In C, every variable must have a data type, which specifies the size and type of values it can store. C is a statically-typed language, meaning a variable's type is fixed once declared.
int (Integer): Used for whole numbers (positive, negative, or zero) without decimal points. Typically 4 bytes, range from -2,147,483,648 to 2,147,483,647.
short int, long int, long long int (for different ranges/sizes), and unsigned versions (for non-negative numbers, doubling the positive range).float (Floating-point): Used for single-precision decimal numbers. Typically 4 bytes, with a range of approx. $1.2 \times 10^{-38}$ to $3.4 \times 10^{38}$. Offers about 6-7 decimal digits of precision.double (Double precision floating-point): Used for double-precision decimal numbers. Typically 8 bytes, with a range of approx. $1.7 \times 10^{-308}$ to $1.7 \times 10^{308}$. Offers about 15-17 decimal digits of precision.long double: Even higher precision floating-point numbers. Size and precision can vary by compiler and architecture (e.g., 10, 12, or 16 bytes).char (Character): Used to store a single character (e.g., 'A', 'b', '7'). Typically 1 byte. Internally, characters are stored as their ASCII (or equivalent) integer values.
_Bool / bool (Boolean): Introduced in C99, requires #include <stdbool.h>. Represents true (1) or false (0).
#include <stdio.h>
#include <stdbool.h> // For bool, true, false
int main() {
// Integer types
int age = 30;
unsigned int population = 8000000000U; // U suffix for unsigned
long long big_number = 123456789012345LL; // LL suffix for long long
// Floating-point types
float temperature = 25.5f; // f suffix for float literal
double pi = 3.1415926535;
long double very_precise_pi = 3.14159265358979323846L; // L suffix for long double
// Character type
char grade = 'A';
char newline_char = '\n'; // Escape sequence for newline
// Boolean type
bool is_active = true;
_Bool has_data = 0; // Using _Bool directly
printf("Age: %d\n", age);
printf("Population: %u\n", population);
printf("Big Number: %lld\n", big_number);
printf("Temperature: %.1f\n", temperature);
printf("Pi (double): %.10lf\n", pi);
printf("Very Precise Pi (long double): %.20Lf\n", very_precise_pi);
printf("Grade: %c\n", grade);
printf("Newline char (ASCII): %d\n", newline_char); // Prints ASCII value
printf("Is Active: %d\n", is_active);
printf("Has Data: %d\n", has_data);
return 0;
}
Age: 30
Population: 8000000000
Big Number: 123456789012345
Temperature: 25.5
Pi (double): 3.1415926535
Very Precise Pi (long double): 3.14159265358979323846
Grade: A
Newline char (ASCII): 10
Is Active: 1
Has Data: 0
auto, static, extern, register) that define the lifetime, scope, and linkage of variables.lvalue vs. rvalue: An lvalue refers to a memory location that can be assigned to (e.g., a variable). An rvalue refers to a temporary value that cannot be assigned to (e.g., a literal or the result of an expression).10, 3.14, 'A', "Hello").const keyword: Declares a variable whose value cannot be changed after initialization.#define preprocessor directive: Creates symbolic constants, which are replaced by their values by the preprocessor before compilation.volatile keyword: A type qualifier that tells the compiler that a variable's value can be changed by something outside of the program's explicit control (e.g., hardware, another thread). This prevents the compiler from optimizing away reads/writes to this variable.restrict keyword (for pointers): A hint to the compiler that a pointer is the sole initial means of accessing the object it points to. This allows for more aggressive optimizations.
#include <stdio.h>
#define MAX_VALUE 100 // Symbolic constant
int global_var = 50; // Global variable (data segment/BSS)
void function_scope_example() {
int local_var = 10; // Local variable (stack)
static int static_var = 0; // Static local variable (data segment/BSS), retains value across calls
static_var++;
printf("Inside function: local_var = %d, static_var = %d\n", local_var, static_var);
}
int main() {
int x = 10; // Variable declaration and initialization (lvalue)
const int immutable_val = 20; // Constant variable
printf("x = %d\n", x);
printf("MAX_VALUE = %d\n", MAX_VALUE);
printf("immutable_val = %d\n", immutable_val);
printf("global_var = %d\n", global_var);
x = 15; // Modifying a variable
// immutable_val = 25; // Error: cannot assign to read-only variable
int result = x + 5; // x is lvalue, 5 is rvalue, x+5 is rvalue
printf("Result of x + 5 = %d\n", result);
function_scope_example(); // Call function once
function_scope_example(); // Call function again
// Volatile example (simplified, usually for hardware interaction)
volatile int sensor_reading = 0;
printf("Sensor reading: %d\n", sensor_reading);
// Imagine an interrupt changes sensor_reading here
printf("Sensor reading (after potential change): %d\n", sensor_reading); // Compiler won't optimize this read away
return 0;
}
x = 10
MAX_VALUE = 100
immutable_val = 20
global_var = 50
Result of x + 5 = 15
Inside function: local_var = 10, static_var = 1
Inside function: local_var = 10, static_var = 2
Sensor reading: 0
Sensor reading (after potential change): 0
(Note: The "after potential change" output for volatile would only show a difference if sensor_reading was actually modified by an external factor between the printf calls in a real-world scenario.)
How a C program interacts with the user (getting input) and displays information (giving output).
printf(): Used for formatted output to the console. Uses format specifiers (e.g., %d for int, %f for float, %c for char, %s for string, %lf for double, %Lf for long double).scanf(): Used for formatted input from the console. Requires the address of the variable using the & operator.
#include <stdio.h>
int main() {
int num;
float price;
char initial;
char name[20]; // Character array for string
printf("Enter an integer: ");
scanf("%d", &num);
printf("Enter a price (e.g., 19.99): ");
scanf("%f", &price);
// Clear input buffer before reading char/string
while (getchar() != '\n'); // Consume remaining newline character
printf("Enter your initial: ");
scanf("%c", &initial);
// Clear input buffer again
while (getchar() != '\n');
printf("Enter your first name: ");
// scanf("%s", name); // scanf for string stops at whitespace.
fgets(name, sizeof(name), stdin); // Better for strings with spaces, reads newline
printf("\nYou entered:\n");
printf("Integer: %d\n", num);
printf("Price: %.2f\n", price);
printf("Initial: %c\n", initial);
printf("Name: %s", name); // Note: fgets includes newline, so no \n here
return 0;
}
Enter an integer: 123
Enter a price (e.g., 19.99): 45.67
Enter your initial: J
Enter your first name: John Doe
You entered:
Integer: 123
Price: 45.67
Initial: J
Name: John Doe
(User input is shown on the same line as the prompt in this example. `fgets` reads the newline character, so `printf` for `Name` does not need `\n`.)