D   A   T   A   W   O   K

Creation: March 22 2016
Modified: February 05 2022

Data Abstraction in C

This article is part of a series that faces the implementation of four of the most fundamental concepts of object-oriented programming using the standard C programming language:

I assume that you are already familiar with object-oriented programming. Thus, for every subject, a very short theoretical introduction is given.

Data abstraction is a programming (and design) technique that relies on the separation of interface and implementation.

As a simple example, think about a "person". When, in every day life, we think about a person (unless you are a doctor) we abstract from things like how a person internally "works". We are just interested in the ways we can interact with a person, to its interface.

The type interface is a key concept. It describes what is the set of actions that an object of a specific type can perform; things like talk, walk, eat and dance, if we are still talking about a person.

Any modern object oriented language define a special syntax to define a type interface. Any interface functionality is strictly bounded to the class type itself using public member functions (often called methods).

For our example we will implement a stack data type. The type is a very common container which supports, at least, the following set of operations:

In the C++ language we can define the type as follows

class stack {
    typedef float value_type;
    size_t size() const;
    void push(value_type val);
    value_type pop();
    value_type peek() const;
    value_type *data;
    size_t      size;

Ignoring the interface implementation, the crucial point here is that when we invoke an object member function, the compiler implicitly pass a hidden argument to the function. This argument, often simply named "this", is a pointer to the involved object.

With a language such as C we don't have such a dedicated feature and the data is always separated from the interface. Anyway we can emulate the OO languages idea by passing to every function that is supposed to be part of the interface a pointer to the object structure as an explicit argument.

Structure definition:

typedef float stack_value_t;

typedef struct stack {
    stack_value_t  *data;
    size_t          size;
} stack_t;

Stack interface

void stack_construct(stack_t *self);
void stack_destroy(stack_t *self);

size_t stack_size(const stack_t *self);

void stack_push(stack_t *self, stack_value_t val);
stack_value_t stack_pop(stack_t *self);
stack_value_t stack_peek(const value_t *self);

Even though we've implemented data abstraction as an emulation of an OO language feature, object oriented programming using C was used by programmers extensively even before the OO languages nobilitated it as an effective programming paradigm and a feature deeply embedded in the language itself.

Example sources download

Proudly self-hosted on a cheap Raspberry Pi