Skip to content

C Variables — Data Types, Declarations, and Memory Size Explained

DodaTech Updated 2026-06-28 8 min read

In this tutorial, you will learn about C Variables. We cover key concepts, practical examples, and best practices to help you master this topic.

C variables are named memory locations that store data of specific types. Understanding how different types use memory is fundamental to writing efficient C programs.

Why It Matters

Unlike higher-level languages, C requires you to declare the type of every variable before using it. This type system determines how much memory is allocated, how values are stored, and what operations are allowed. Choosing the right type affects program correctness, memory usage, and performance. In systems programming where every byte counts, understanding exact type sizes and ranges is critical.

Real-World Use

Embedded Systems with 2 KB of RAM need to store sensor readings in the smallest possible type. A temperature reading that fits in a char (1 byte) should never use an int (4 bytes). Network protocols specify exact field sizes in bits -- C's fixed-width integer types map directly to protocol specifications. Durga Antivirus Pro uses unsigned char arrays for buffer scanning and fixed-width int32 types for file offsets.

What You Will Learn

  • Declaring and initializing variables in C
  • Integer types: int, short, long, signed, unsigned
  • Floating-point types: float and double
  • The char type and its dual role as character and small integer
  • Using sizeof to determine type sizes
  • Type ranges and what happens when values overflow

Learning Path

flowchart LR
  A[Hello World] --> B[Variables
You are here] B --> C[Constants] C --> D[Operators] D --> E[Control Flow] style B fill:#f90,color:#fff

Variable Declaration and Initialization

In C, you must declare a variable before using it. Declaration tells the compiler the variable's name and type. Initialization assigns it a starting value.

#include <stdio.h>

int main() {
    // Declaration
    int age;
    
    // Initialization
    age = 25;
    
    // Declaration + initialization in one statement
    int count = 100;
    double price = 19.99;
    char grade = 'A';
    
    printf("Age: %d, Count: %d, Price: %.2f, Grade: %c\n",
           age, count, price, grade);
    // Age: 25, Count: 100, Price: 19.99, Grade: A
    
    return 0;
}

Expected output: Age: 25, Count: 100, Price: 19.99, Grade: A

Integer Types

C provides several integer types with different sizes and ranges:

#include <stdio.h>
#include <limits.h>

int main() {
    char c = 'A';           // 1 byte, typically -128 to 127
    unsigned char uc = 255;  // 1 byte, 0 to 255
    short s = 32000;        // 2 bytes, typically -32,768 to 32,767
    unsigned short us = 65000; // 2 bytes, 0 to 65,535
    int i = 1000000;         // 4 bytes, typically -2B to 2B
    unsigned int ui = 4000000000U; // 4 bytes, 0 to 4.2B
    long l = 1000000000L;   // 4 or 8 bytes depending on platform
    long long ll = 1000000000000LL; // 8 bytes, very large
    
    printf("char: %zu bytes\n", sizeof(char));
    printf("int: %zu bytes\n", sizeof(int));
    printf("long: %zu bytes\n", sizeof(long));
    printf("long long: %zu bytes\n", sizeof(long long));
    
    printf("INT_MAX: %d\n", INT_MAX);
    printf("INT_MIN: %d\n", INT_MIN);
    
    return 0;
}

Expected output (64-bit system):

char: 1 bytes
int: 4 bytes
long: 8 bytes
long long: 8 bytes
INT_MAX: 2147483647
INT_MIN: -2147483648

Type Sizes Are Platform-Dependent

The C standard does not specify exact sizes for most types. It only guarantees:

  • char is at least 8 bits
  • short is at least 16 bits
  • int is at least 16 bits (usually 32 on modern systems)
  • long is at least 32 bits (64 on Unix, 32 on Windows)
  • long long is at least 64 bits

Always use sizeof to check sizes on your platform.

The char Type

In C, char is both a character type and the smallest integer type. Characters are stored as their ASCII numeric values:

#include <stdio.h>

int main() {
    char letter = 'A';
    printf("Character: %c\n", letter);  // A
    printf("ASCII value: %d\n", letter);  // 65
    
    // char as a small integer
    char small = -10;
    unsigned char positive = 200;
    
    printf("Small integer: %d\n", small);      // -10
    printf("Unsigned char: %u\n", positive);    // 200
    
    // Beware: char can be signed or unsigned depending on platform
    signed char sc = -128;   // always signed
    unsigned char usc = 255;  // always unsigned
    
    return 0;
}

Expected output:

Character: A
ASCII value: 65
Small integer: -10
Unsigned char: 200

The fact that char is a tiny integer is important for memory-efficient data storage. An array of 1000 characters uses only 1 KB of memory.

Floating-Point Types

Floating-point types represent real numbers with fractional parts:

#include <stdio.h>
#include <float.h>

int main() {
    float f = 3.14159f;       // 4 bytes, ~7 decimal digits
    double d = 3.141592653589793; // 8 bytes, ~15 decimal digits
    long double ld = 3.141592653589793238L; // 10/16 bytes, more precision
    
    printf("float: %zu bytes, value: %.7f\n", sizeof(float), f);
    printf("double: %zu bytes, value: %.15f\n", sizeof(double), d);
    printf("long double: %zu bytes\n", sizeof(long double));
    
    printf("FLT_MAX: %e\n", FLT_MAX);
    printf("DBL_MAX: %e\n", DBL_MAX);
    
    return 0;
}

Expected output:

float: 4 bytes, value: 3.1415901
double: 8 bytes, value: 3.141592653589793
long double: 16 bytes
FLT_MAX: 3.402823e+38
DBL_MAX: 1.797693e+308

Use float when memory is constrained and you do not need high precision. Use double for general-purpose scientific computing. The f suffix on 3.14159f makes it a float literal; without the suffix, it is a double.

Variable Naming Rules

Variables in C follow naming rules:

  • Must start with a letter or underscore
  • Can contain letters, digits, and underscores
  • Case-sensitive: age and Age are different variables
  • Cannot use C keywords like int, return, if
  • Avoid leading underscores (reserved for system use)

The sizeof Operator

sizeof is a compile-time operator that returns the size of a type or variable in bytes:

#include <stdio.h>

int main() {
    int arr[10];
    struct Point { int x; int y; };
    
    printf("sizeof(int): %zu\n", sizeof(int));
    printf("sizeof(arr): %zu\n", sizeof(arr));
    printf("sizeof(struct Point): %zu\n", sizeof(struct Point));
    printf("Number of elements: %zu\n", sizeof(arr) / sizeof(arr[0]));
    
    return 0;
}

Expected output:

sizeof(int): 4
sizeof(arr): 40
sizeof(struct Point): 8
Number of elements: 10

The formula sizeof(arr) / sizeof(arr[0]) is the standard way to get the element count of an array.

Type Overflow

When a value exceeds the maximum for its type, it wraps around (unsigned) or produces undefined behavior (signed):

#include <stdio.h>
#include <limits.h>

int main() {
    unsigned int u = UINT_MAX;
    printf("Max unsigned: %u\n", u);
    printf("Plus one: %u\n", u + 1);  // Wraps to 0
    
    signed int s = INT_MAX;
    printf("Max signed: %d\n", s);
    printf("Plus one: %d\n", s + 1);  // Undefined behavior!
    
    return 0;
}

Unsigned overflow wraps around predictably (modulo arithmetic). Signed overflow is undefined behavior -- the compiler may optimize it in unexpected ways.

Common Mistakes

1. Using Uninitialized Variables

int x;
printf("%d", x);  // Uses garbage value

Always initialize variables before reading them.

2. Integer Overflow

int x = 2000000000;
int y = x * 2;  // Overflow, undefined behavior for signed

Use larger types or check bounds.

3. Assuming Fixed Type Sizes

long x = 1000000000000;  // OK on 64-bit, overflow on 32-bit

Use int32_t, int64_t from <stdint.h> for fixed sizes.

4. Confusing char Signedness

char c = 200;  // If char is signed, this overflows

Use unsigned char or signed char explicitly when the signedness matters.

5. Forgetting the f Suffix on Float Literals

float f = 3.14;  // 3.14 is a double, converted to float
float f2 = 3.14f;  // Explicit float literal

The f suffix prevents unnecessary double-to-float conversion warnings.

Practice Questions

  1. What does sizeof(int) return on your system? Run printf("%zu", sizeof(int)) to find out. Typically 4 bytes on modern systems.

  2. What is the difference between char and unsigned char? char may be signed or unsigned depending on the platform. unsigned char always holds values 0 to 255.

  3. What happens when an unsigned integer overflows? It wraps around modulo (max + 1). For example, UINT_MAX + 1 equals 0.

  4. Why might you choose float over double? To save memory when high precision is not needed. A float uses 4 bytes versus double's 8 bytes.

  5. Challenge: Write a program that prints the size and range of every integer type in <limits.h>.

Mini Project: Type Size Printer

Write a program that reports the exact sizes and ranges of all fundamental types:

#include <stdio.h>
#include <limits.h>
#include <float.h>

int main() {
    printf("Type            Bytes   Min                 Max\n");
    printf("----            -----   ---                 ---\n");
    printf("char            %-5zu  %-20d %-20d\n",
           sizeof(char), CHAR_MIN, CHAR_MAX);
    printf("unsigned char   %-5zu  %-20d %-20d\n",
           sizeof(unsigned char), 0, UCHAR_MAX);
    printf("short           %-5zu  %-20d %-20d\n",
           sizeof(short), SHRT_MIN, SHRT_MAX);
    printf("int             %-5zu  %-20d %-20d\n",
           sizeof(int), INT_MIN, INT_MAX);
    printf("unsigned int    %-5zu  %-20d %-20u\n",
           sizeof(unsigned int), 0, UINT_MAX);
    printf("long            %-5zu  %-20ld %-20ld\n",
           sizeof(long), LONG_MIN, LONG_MAX);
    printf("float           %-5zu  %-20e %-20e\n",
           sizeof(float), FLT_MIN, FLT_MAX);
    printf("double          %-5zu  %-20e %-20e\n",
           sizeof(double), DBL_MIN, DBL_MAX);
    return 0;
}

FAQ

What is the difference between declaration and definition?

Declaration introduces a name and type. Definition allocates storage. 'int x;' is both a declaration and definition. 'extern int x;' is only a declaration.

Can I change a variable's type after declaration?

No. C is statically typed. Once you declare 'int x;', x is always an int. You cannot change it to float later.

What does unsigned mean?

Unsigned means the variable cannot hold negative values. The range shifts from [-n/2, n/2-1] to [0, n-1], giving you twice the positive range.

Is char always 1 byte?

Yes, char is always exactly 1 byte by the C standard. However, a byte may be more than 8 bits on exotic platforms (rare).

How do I print a long long?

Use %lld for signed long long and %llu for unsigned long long in printf format strings.

What is Next

Now that you understand variables, proceed to Constants in C to learn about const qualifiers, #define macros, enum constants, and literal suffixes.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro

Home Browse C