The VikiD Truth

Knowledge base / Computing / C & systems languages

Objects in C

Here is the truth about “objects” in C: they have nothing to do with classes. When the C standard says object, it means something much plainer and much more useful: a chunk of memory that can hold a value. Every variable you declare, every element of an array, every block you malloc is an object. Once you see that, half of C’s “undefined behaviour” warnings start to make sense.

What it is, in plain words

The C standard (C23 is the current edition, with C2y in progress in 2026) defines an object as a region of data storage in the execution environment, the contents of which can represent values.

Every object has four properties worth knowing:

  1. Size – how many bytes it occupies, given by sizeof.
  2. Type – how those bytes are to be interpreted (int, double, struct point). This is the object’s effective type.
  3. Alignment – which addresses it may start at (alignof, usually 4 or 8 for int and double).
  4. Storage duration – how long it lives:
    • automatic: local variables, alive until the block ends;
    • static: globals and static locals, alive for the whole program;
    • thread: thread_local (C23 spelling; _Thread_local before), one per thread;
    • allocated: from malloc/calloc/realloc, alive until free.

A variable is just an object that has a name, an identifier. An lvalue is an expression that designates an object, which is why you can assign to x, a[3] or *p but not to x + 1.

Why it matters

Most serious C bugs are object bugs:

Each of these is “the program used memory that was not a live object of the right type”. Thinking in objects is how you reason about them before the debugger has to.

An everyday analogy: lockers

Memory is a corridor of numbered lockers. An object is a set of adjacent lockers you have been assigned, with a label on the door saying what goes inside (the type) and a rental period (the storage duration). A pointer is a slip of paper with a locker number on it. The slip can outlive the rental. Opening a locker you no longer rent is not a crime the corridor will stop. It just gives you someone else’s stuff, or nothing, or a mess. That is undefined behaviour.

A hands-on example

#include <stdio.h>
#include <stdlib.h>
#include <stdalign.h>

static int counter;              /* static storage: lives all program long */

int *bad(void) {
    int local = 42;              /* automatic storage */
    return &local;               /* dangling: local dies on return */
}

int main(void) {
    double d = 3.14;             /* an object of type double */
    int a[4] = {1, 2, 3, 4};     /* one array object holding four int objects */
    int *heap = malloc(sizeof *heap * 4);   /* allocated object */

    printf("sizeof d = %zu, alignof(double) = %zu\n", sizeof d, alignof(double));
    printf("sizeof a = %zu, elements = %zu\n", sizeof a, sizeof a / sizeof a[0]);

    a[2] = 99;                   /* a[2] is an lvalue designating an object */
    counter++;

    free(heap);                  /* heap object's lifetime ends here */
    /* heap[0] = 1;  <- would be use-after-free */
    return 0;
}

Compile with the sanitizers and the compiler will catch object mistakes at run time:

gcc -std=c23 -Wall -Wextra -g -fsanitize=address,undefined object.c -o object
./object

Uncomment the heap[0] = 1; line and AddressSanitizer reports heap-use-after-free with the exact line. Call bad() and dereference the result and GCC warns at compile time that you return the address of a local. Step through it in GDB and print sizeof(a) or ptype a to see the object’s type from the inside.

Common misconceptions

Connections

Back to C Programming

In C, the term object refers to a location in memory whose contents can represent values.

Objects that have named identifiers are called variables.

Last edited · 4 revisions

Tags: #Computing