structs

Table of contents

  1. Definitions
    1. struct
    2. typedef
  2. Example
  3. Bigger example
  4. References

Definitions

struct

A struct is somewhat analogous to a class in Java or a dataclass in Python.

// Declaration of a struct called student
struct student {
    int id;
    int slug_points;
}

// Analogous to saying "int Sammy", the type here is a "struct student"
struct student Sammy;
Sammy.id = 1234;
Sammy.slug_points = 0; // oh no

// Analogous to "int Bob = 1", intialize in order of the fields declared in the struct definition
struct student Bob = { 5678, 1 };

“A member of a particular structure is referred to in an expression bya construction of the form: structure-name.member” (p.128)

“If p is a pointer to a structure, then [accessing a member would be:] p->member-of-structure” (p.131)

typedef

typedef is used to declare new names for datatypes.

// Alias type A to be called B
typedef A B

There is no “creating” new datatypes within C, the closest concept to this would be declaring a new struct that is typedef‘ed to an identifier.

Example

This example makes a new struct called AObj and then typedef’s a pointer to the struct to be called A for ease of use.

This is a very common pattern within C programming, become comfortable with it.

// Typedefing a pointer to this struct to be called A
// i.e, instead of saying "struct AObj*", can refer to it as A
typedef struct AObj* A;

typedef struct AObj {
    int a;
    int b;
    A another;
} AObj; // shortcutting "struct AObj" to be called just AObj

// When using the direct struct, access fields with .
AObj obj;
obj.a = 1;

// When using a pointer to a struct, use ->
A ptr_obj;
ptr_obj->a = 1;

The first typedef might be confusing, how can you define a pointer to struct AObj before you define said struct? Note that this only works for pointers to structs, since C trusts that you will eventually define struct AObj before you use A.

Bigger example

This example’s purpose is two-fold: showcase the call-by-value aspect of C, and showcase using structs within your programs.

#include <stdio.h>

struct AObj {
    int a;
    int b;
    int c;
};

// Make it easier to refer to AObj
// type: struct AObj, new name: AObj
typedef struct AObj AObj;
typedef AObj* A;

// Shortcut of declaring a struct type, and making its name easier to reference
typedef struct BObj {
    A aobj;
    int a;
} BObj;
typedef BObj* B;

void another(A aobj) {
    // Structures can only be copied or moved around using pointers
    // Copying can be inefficient, generally appreciated to use pointers
    printf("aobj->b = %d\n\n", aobj->b);
}

int main() {
    struct AObj first;
    AObj second = {1, 2, 3};

    // Accessing from a struct, the . operator (p.128)
    printf("Field b of second struct: second.b = %d\n\n", second.b);

    // Pointer to a struct, typedef (p.221)
    // pobj->member is a shortcut from having to do (*obj).member (p.131)
    A third = &second;
    printf("third points to the second struct: third->b = %d\n\n", third->b);

    // Using pointers and/or address-of & to move structs around in programs
    printf("another(&second)\n\t");
    another(&second);

    printf("another(third)\n\t");
    another(third);

    // structs within another structs (p.131)
    BObj fourth = {third, 0};
    B fifth = &fourth;

    printf("struct-ception: . and -> are left-to-right associative\n\t");
    printf("fourth.aobj->b = fifth->aobj->b = %d\n", fifth->aobj->b);

    return 0;
}

The output of this program is:

Field b of second struct: second.b = 2

third points to the second struct: third->b = 2

another(&second)
	aobj->b = 2

another(third)
	aobj->b = 2

struct-ception: . and -> are left-to-right associative
	fourth.aobj->b = fifth->aobj->b = 2

References

  1. K&R, Chapter 6: Structures (page 127)
    • 6.1 - Basics of Structures
    • 6.2 - Structures and Fucntions
    • 6.4 - Pointers to Structures
    • 6.7 - Typedef