Mastering C Language Data Types and Variables

Fundamental Data Types

In C, every stored value must be assigned a type that dictates its memory footprint and how the compiler interprets the bits. The core categories are outlined below.

Integer Types

Integers represent whole numbers without fractional components. C provides multiple widths to balance memory usage and range requirements.

// Short integer variations
short int sh_val;
unsigned short int ush_val;

// Standard integer variations
int std_int;
signed int s_int;

// Long integer variations
long int lg_val;
unsigned long int ulg_val;

// Extended integer (ISO C99)
long long int ll_val;
unsigned long long int ull_val;

Floating-Point Types

Floating-point types handle real numbers with decimal precision. Precision increases alongside memory allocation.

float single_prec;    // Typically 32-bit IEEE 754
double double_prec;   // Typically 64-bit IEEE 754
long double ext_prec; // Implementation-defined precision

Character Types

The char type stores individual ASCII or extended character sets. It behaves identically to an 8-bit integer under the hood.

char asc_val;
signed char s_char;
unsigned char u_char;

Boolean Representation

Historically, C treated zero as false and any non-zero value as true. ISO C99 introduced a dedicated boolean type via the _Bool keyword.

#include <stdbool.h>

bool flag_true = true;
bool flag_false = false;

Memory Sizing with sizeof

The sizeof operator returns the byte count required to store a given entity. It operates at compile time and does not evaluate expressions, only their resulting types.

#include <stdio.h>

int main(void) {
    int sample = 42;
    printf("Byte size of sample: %zu bytes\n", sizeof(sample));
    printf("Byte size of int: %zu bytes\n", sizeof(int));
    printf("Byte size of expression result: %zu bytes\n", sizeof(10 + 3.14));
    return 0;
}

The operator yields an unsigned integer type, standardized as size_t. When printing this value, use %zu to avoid platform-specific warnings. Common storage conversions: 1 Byte = 8 bits, 1 KB = 1024 Bytes, scaling continues through MB, GB, and beyond.


Signed and Unsigned Modifiers

These keywords control whether a numeric type can represent negative values.

  • signed: Allows both positive and negative values. For int, this is implicit and usually omitted.
  • unsigned: Restricts values to zero and positives. This effectively doubles the maximum positive range by repurposing the sign bit for magnitude.

Important: The default signedness of char depends on the architecture and compiler settings. Explicitly declaring signed char or unsigned char guarantees predictable behavior across platforms.


Value Range Limits

Rather than hardcoding boundaries, portable C code references header constants. <limits.h> defines integer bounds, while <float.h> handles floating-point limits.

Macro Description
INT_MIN / INT_MAX Minimum/Maximum int
UINT_MAX Maximum unsigned int
LONG_LONG_MIN / LLONG_MAX Bounds for long long
FLT_MIN / DBL_MAX Floating-point thresholds

Variables and Scope

A variable allocates named memory space to hold mutable data. Proper declaration follows strict syntax and naming conventions.

Declaration and Initialization

type_specifier identifier = initial_value;

Naming rules: identifiers must begin with a letter or underscore, contain only alphanumeric characters and underscores, and cannot match reserved keywords. Assigning a value at the moment of creation is called initialization.

Storage Duration and Scope

  • Local Variables: Declared inside braces {}. Stored in the stack segment. Accessible only within their defining block.
  • Global Variables: Declared outside all functions. Reside in the static/data segment. Visible program-wide unless shadowed.

When a local and global variable share the same name, the local scope takes precedence. Direct memory access to these regions is abstracted by the compiler; developers interact with them through symbols.


Arithmetic Operators

Binary arithmetic operators perform mathematical operations on two operands.

  • +, -, *: Addition, subtraction, multiplication.
  • /: Division performs truncation toward zero when operating on integers.
  • %: Modulo returns the remainder. Requires integer operands only.

For negative modulo results, the sign follows the left operand (e.g., -7 % 3 yields -1).


Assignment and Compound Operators

Initial assignment occurs during declaration. Subsequent assignments modify existing values.

int counter = 0;  // Initialization
counter = 15;     // Reassignment

Chained assignment (a = b = c) executes right-to-left but reduces readability. Compound operators merge an operation with assignment:

x += 5;   // Equivalent to x = x + 5
y *= 2;   // Equivalent to y = y * 2
z >>= 1;  // Right shift assignment

Supported combinations include +=, -=, *=, /=, %=, <<=, >>=, &=, |=, and ^=.


Unary Operators

Unary operators act on a single operand.

Increment and Decrement

  • Prefixed (++x, --x): Modify the value first, then yield the updated result.
  • Suffixed (x++, x--): Yield the current value, then modify.

Unary Plus and Minus

+x leaves the value unchanged. -x negates the operand, useful for type promotion or explicit sign invertion.


Explicit Type Casting

Cast operators force temporary type conversion. Syntax places the target type in parentheses before the expression.

double fraction = 9.8;
int truncated = (int)fraction;  // Result: 9
int ratio = (int)(20.0 / 3.0);  // Integer division after cast

Casting does not alter the original variable's type. Misusing casts can trigger silent overflow or precision loss.


Formatted Input and Output

The standard I/O library (<stdio.h>) provides printf for console output and scanf for keyboard input.

printf Formatting

Format strings combine literal text with conversion specifiers. Each specifier begins with % and expects a corresponding argument.

int score = 88;
double rate = 0.95;
printf("Performance: %d%% | Ratio: %.2f\n", score, rate);

Common specifiers include %d (signed int), %u (unsigned int), %f (float/double), %lf (explicit double), %c (character), %s (string), and %zu (size_t). Width and precision modifiers refine output layout:

  • Width padding: %10d reserves ten character slots, right-aligning numbers.
  • Sign display: %+d forces + prefix for positive values.
  • Decimal precision: %.3f rounds to three fractional digits.
  • Truncated strings: %.5s prints only the first five characters.

scanf Input Handling

scanf parses keyboard streams according to a format string. Unlike printf, scalar arguments require the address-of operator & to store results.

int id;
char initial;
scanf("%d", &id);           // Reads integer into 'id'
scanf(" %c", &initial);     // Space before %c consumes leading whitespace

Key behaviors:

  • Whitespace in the format string automatically skips tabs, spaces, and newlines in input, except for %c and %[ ].
  • Returns the count of successfully assigned items, or EOF on termination/error.
  • %s reads until the next whitespace delimiter. To prevent buffer overflow, always specify maximum field width: %19s for a 20-byte array (reserving space for \0).
  • Assignment suppression: Prefixing a specifier with * discards the matched input without storing it: scanf("%d-%*s-%d", &a, &b);

Tags: c-data-types variable-scope sizeof-operator floating-point-representation stdi-o-library

Posted on Sun, 11 Oct 2026 16:38:28 +0000 by Matt Parsons