Docs

README

Variables and Constants in C

šŸ“– Introduction

Variables are named storage locations in memory that hold data which can be modified during program execution. Constants are values that remain fixed throughout the program. Understanding how to properly declare, initialize, and use variables and constants is fundamental to C programming.


šŸŽÆ What is a Variable?

A variable is a symbolic name for a memory location where data is stored. Think of it as a labeled box that can hold a value.

Memory Representation:
ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”
│                      RAM                                     │
ā”œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¬ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¬ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¬ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¬ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¬ā”€ā”€ā”€ā”€ā”€ā”€ā”¤
│ Address  │ 0x1000   │ 0x1004   │ 0x1008   │ 0x100C   │ ...  │
ā”œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¼ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¼ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¼ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¼ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¼ā”€ā”€ā”€ā”€ā”€ā”€ā”¤
│ Name     │   age    │  salary  │  grade   │  ...     │      │
ā”œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¼ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¼ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¼ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¼ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¼ā”€ā”€ā”€ā”€ā”€ā”€ā”¤
│ Value    │    25    │  50000   │   'A'    │  ...     │      │
ā”œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¼ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¼ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¼ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¼ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¼ā”€ā”€ā”€ā”€ā”€ā”€ā”¤
│ Type     │   int    │   int    │   char   │  ...     │      │
ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”“ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”“ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”“ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”“ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”“ā”€ā”€ā”€ā”€ā”€ā”€ā”˜

Properties of a Variable:

  1. •Name (identifier) - How we refer to the variable
  2. •Type - What kind of data it holds
  3. •Value - The actual data stored
  4. •Address - Location in memory
  5. •Scope - Where the variable is accessible
  6. •Lifetime - How long it exists in memory

šŸ“ Variable Declaration

Syntax:

data_type variable_name;

Examples:

int age;              // Declares an integer variable
float salary;         // Declares a float variable
char grade;           // Declares a character variable
double pi;            // Declares a double variable

Multiple Declarations:

// Multiple variables of same type on one line
int x, y, z;
float width, height, depth;

// Each on separate line (preferred for readability)
int count;
int total;
int average;

šŸš€ Variable Initialization

Initialization means giving a variable its first value.

Syntax:

data_type variable_name = initial_value;

Examples:

int age = 25;                    // Integer
float price = 19.99f;            // Float (note 'f' suffix)
double pi = 3.14159265358979;    // Double
char grade = 'A';                // Character
char name[] = "John";            // String (character array)

Declaration vs Initialization:

int x;          // Declaration only (contains garbage)
x = 10;         // Assignment (later initialization)

int y = 20;     // Declaration with initialization (preferred)

āš ļø Warning: Uninitialized Variables

int x;          // Uninitialized!
printf("%d", x); // DANGER: Prints garbage value

// Always initialize:
int x = 0;      // Safe

šŸ“› Variable Naming Rules

āœ… Valid Rules:

  1. •Start with letter or underscore - Not a digit
  2. •Contain letters, digits, underscores - No special characters
  3. •Case-sensitive - age, Age, AGE are different
  4. •No reserved keywords - Can't use int, for, while, etc.
  5. •No length limit - But first 31-63 characters are significant

Examples:

ValidInvalidReason
age2ageStarts with digit
_countmy-varContains hyphen
myVarmy varContains space
student1intReserved keyword
MAX_SIZE#defineContains #
_123floatReserved keyword

Naming Conventions:

// camelCase - Common in C
int studentAge;
float accountBalance;
char firstName[50];

// snake_case - Also common in C
int student_age;
float account_balance;
char first_name[50];

// ALL_CAPS - For constants and macros
#define MAX_SIZE 100
const int BUFFER_SIZE = 256;

// Hungarian notation - Prefix with type hint
int nAge;           // n for number/int
float fPrice;       // f for float
char *pName;        // p for pointer
char szBuffer[100]; // sz for string (zero-terminated)

šŸ’” Best Practices:

  1. •Use meaningful names: studentAge not sa
  2. •Be consistent: Pick one convention and stick to it
  3. •Avoid single letters: Except for loop counters (i, j, k)
  4. •Don't use reserved words: Even as part of names
  5. •Consider scope: Longer names for wider scope

šŸ”’ Constants

Constants are values that cannot be changed after initialization.

Types of Constants in C:

                    Constants in C
                          │
        ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¼ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”
        │                 │                 │
   Literal           Symbolic           Defined
   Constants         Constants           Constants
        │                 │                 │
   42, 3.14         const int          #define MAX 100
   'A', "Hi"        PI = 3.14

1. Literal Constants

Values written directly in code:

// Integer literals
int a = 42;          // Decimal
int b = 052;         // Octal
int c = 0x2A;        // Hexadecimal

// Floating-point literals
float f = 3.14f;
double d = 3.14;
double e = 6.022e23; // Scientific notation

// Character literals
char ch = 'A';
char newline = '\n';

// String literals
char greeting[] = "Hello, World!";

2. const Keyword (C89+)

The const keyword creates a read-only variable:

const int MAX_STUDENTS = 100;
const float PI = 3.14159f;
const char NEWLINE = '\n';

// Attempt to modify causes compile error:
// MAX_STUDENTS = 200;  // ERROR: assignment of read-only variable

const with Pointers:

// Pointer to constant data (can't change data through pointer)
const int *ptr1 = &value;
*ptr1 = 10;  // ERROR: can't modify data
ptr1 = &other;  // OK: can change pointer

// Constant pointer (can't change pointer itself)
int *const ptr2 = &value;
*ptr2 = 10;  // OK: can modify data
ptr2 = &other;  // ERROR: can't change pointer

// Constant pointer to constant data (can't change either)
const int *const ptr3 = &value;
*ptr3 = 10;  // ERROR
ptr3 = &other;  // ERROR

3. #define Preprocessor Directive

Creates symbolic constants (text replacement):

#define PI 3.14159
#define MAX_SIZE 100
#define GREETING "Hello"
#define SQUARE(x) ((x) * (x))

// Usage:
float area = PI * radius * radius;
int array[MAX_SIZE];
printf("%s\n", GREETING);
int sq = SQUARE(5);  // Replaced with ((5) * (5))

const vs #define:

Featureconst#define
Type checkingāœ… YesāŒ No
Debuggingāœ… Has symbolāŒ Replaced before compile
Memoryāœ… Allocates memoryāŒ Text replacement
Scopeāœ… Follows scope rulesāŒ File scope
Can be pointerāœ… YesāŒ No
PreprocessorāŒ Noāœ… Yes
// Prefer const for type safety:
const int MAX_VALUE = 100;

// Use #define for:
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
#define DEBUG_MODE 1

4. enum Constants

Create named integer constants:

enum Color { RED, GREEN, BLUE };  // RED=0, GREEN=1, BLUE=2

enum Weekday {
    MONDAY = 1,    // Start from 1
    TUESDAY,       // 2
    WEDNESDAY,     // 3
    THURSDAY,      // 4
    FRIDAY,        // 5
    SATURDAY,      // 6
    SUNDAY         // 7
};

// Usage:
enum Color myColor = GREEN;
enum Weekday today = FRIDAY;

šŸŒ Variable Scope

Scope determines where a variable can be accessed.

Types of Scope:

#include <stdio.h>

int globalVar = 100;  // GLOBAL SCOPE - accessible everywhere

void function() {
    int localVar = 50;  // LOCAL SCOPE - only in this function

    {
        int blockVar = 25;  // BLOCK SCOPE - only in this block
        printf("%d\n", blockVar);  // OK
    }
    // blockVar not accessible here

    printf("%d\n", localVar);   // OK
    printf("%d\n", globalVar);  // OK
}

int main() {
    printf("%d\n", globalVar);  // OK
    // printf("%d\n", localVar);  // ERROR: not in scope

    for (int i = 0; i < 5; i++) {  // i has block scope (C99+)
        printf("%d ", i);
    }
    // i not accessible here

    return 0;
}

Scope Hierarchy:

ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”
│ Global Scope (file level)                                   │
│  ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”ā”‚
│  │ Function Scope                                          ││
│  │  ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”ā”‚ā”‚
│  │  │ Block Scope                                         │││
│  │  │  ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”ā”‚ā”‚ā”‚
│  │  │  │ Inner Block Scope                               ││││
│  │  │  │  Variables here can access all outer scopes     ││││
│  │  │  ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜ā”‚ā”‚ā”‚
│  │  │  Outer block cannot access inner block variables    │││
│  │  ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜ā”‚ā”‚
│  │  Other functions cannot access local variables          ││
│  ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜ā”‚
│  All code can access global variables                       │
ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜

Variable Shadowing:

int x = 10;  // Global x

void function() {
    int x = 20;  // Local x shadows global x
    printf("%d\n", x);  // Prints 20

    {
        int x = 30;  // Block x shadows local x
        printf("%d\n", x);  // Prints 30
    }

    printf("%d\n", x);  // Prints 20 (back to local x)
}

ā° Variable Lifetime

Lifetime is how long a variable exists in memory.

Storage Classes:

Storage ClassKeywordLifetimeScopeDefault Value
Automaticauto (default)Function callLocalGarbage
StaticstaticProgram durationLocal/GlobalZero
RegisterregisterFunction callLocalGarbage
ExternalexternProgram durationGlobalZero

1. Automatic Variables (auto):

void function() {
    int x = 10;  // auto by default
    auto int y = 20;  // Explicit auto (rarely used)
    // Created when function is called
    // Destroyed when function returns
}

2. Static Variables:

void counter() {
    static int count = 0;  // Initialized only once
    count++;
    printf("Called %d times\n", count);
}

int main() {
    counter();  // Called 1 times
    counter();  // Called 2 times
    counter();  // Called 3 times
    return 0;
}

Static at file level (internal linkage):

static int moduleVar = 0;  // Only accessible in this file
static void helperFunction() { }  // Only callable in this file

3. Register Variables:

void function() {
    register int i;  // Hint: store in CPU register
    for (i = 0; i < 1000000; i++) {
        // Fast access (if compiler honors the hint)
    }
    // Note: Can't take address of register variable
    // int *ptr = &i;  // ERROR
}

4. External Variables (extern):

// file1.c
int sharedVar = 100;  // Definition

// file2.c
extern int sharedVar;  // Declaration (use the one from file1.c)

void function() {
    printf("%d\n", sharedVar);  // Uses sharedVar from file1.c
}

šŸ“Š Variable Initialization Summary

// ============================================
// INITIALIZATION METHODS
// ============================================

// Method 1: Declaration then assignment
int a;
a = 10;

// Method 2: Declaration with initialization (preferred)
int b = 20;

// Method 3: Multiple on one line (same type)
int x = 1, y = 2, z = 3;

// Method 4: Arrays
int arr1[5] = {1, 2, 3, 4, 5};          // Full initialization
int arr2[5] = {1, 2};                    // Partial (rest are 0)
int arr3[] = {1, 2, 3};                  // Size inferred (3)
int arr4[5] = {0};                       // All zeros

// Method 5: Structures
struct Point {
    int x;
    int y;
};
struct Point p1 = {10, 20};              // Positional
struct Point p2 = {.x = 10, .y = 20};    // Designated (C99)

// Method 6: Compound literals (C99)
int *ptr = (int[]){1, 2, 3, 4, 5};

āš ļø Common Mistakes

1. Using Uninitialized Variables:

int x;
printf("%d", x);  // Garbage value!

// Fix: Always initialize
int x = 0;

2. Scope Confusion:

if (condition) {
    int x = 10;
}
printf("%d", x);  // ERROR: x not in scope

// Fix: Declare outside
int x = 0;
if (condition) {
    x = 10;
}
printf("%d", x);  // OK

3. Modifying Constants:

const int MAX = 100;
MAX = 200;  // ERROR: can't modify const

#define VALUE 50
VALUE = 60;  // ERROR: #define is not a variable

4. Naming Conflicts:

int int = 5;      // ERROR: 'int' is keyword
int float = 3.14; // ERROR: 'float' is keyword

āœ… Best Practices

  1. •Always initialize variables at declaration
  2. •Use meaningful names that describe the purpose
  3. •Prefer const over #define for typed constants
  4. •Minimize global variables - they make code harder to maintain
  5. •Declare variables close to first use (C99+ allows mid-block)
  6. •Use static for file-local globals to prevent external access
  7. •Comment non-obvious initializations

šŸ”‘ Key Takeaways

  1. •Variables store data that can change during execution
  2. •Constants store values that cannot be modified
  3. •Declaration creates the variable; initialization gives it a value
  4. •Scope determines where a variable is accessible
  5. •Lifetime determines how long a variable exists
  6. •Use const for type-safe constants
  7. •Always initialize to avoid undefined behavior

ā­ļø Next Topic

Continue to Input/Output (scanf, printf) to learn how to read and display data.

README - C Programming Tutorial | DeepML