STRUCTURES

Structures

Article by:
Date Published:
Last Modified:

Overview

Structures (also called structs) is a way in C to group several related variables into a larger variable. They are also supported in C++, although classes are normally used instead (one of the key differences between the two in C++ is that struct members are public by default, classes members are private by default).

Basic Usage

For example, the following code declares a struct that represents an error, and encapsulates an errorCode and an errorString:

1
2
3
4
struct error {
    uint8_t errorCode;
    char * errorString;
};

This only declares the struct, to use one we must create an instance of it. Then members can be accessed with the dot (.) operator:

1
2
3
4
5
int main() {
    struct error myError;
    myError.errorCode = 4;
    myError.errorString = "User error";
}

Using Typedef

The typedef keyword can be used when defining a struct:

1
2
3
4
typedef struct {
    uint8_t errorCode;
    char * errorString;
} error_t;

And then instead of creating an instance with struct error <variable_name>, you can use error_t <variable_name> like so:

1
2
3
4
5
int main() {
    error_t myError;
    myError.errorCode = 4;
    myError.errorString = "User error";
}

Initialising Structures

Initialising structures is way of defining what the values of the variables inside the struct will be at the time of creation. Note that there is a big syntax difference between initialising structures in C and in C++.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
// Defining a structure type
typedef struct
{
    uint16_t value1;
    uint16_t value2;
} demoStruct_t;

// Creating a structure and initialising the variables
// Note that this is won't work in C++
demoStruct_t struct1 =
{
    .value1 = 560;
    .value2 = 34;
}

Unfortunately, you cannot define default variables for a structure when you declare it, only when you create an instance of that structure type. If this is annoying you, you might want to consider switching to C++, which allows you to do such a thing by using the class and constructor mechanisms.

Copying Structures

You can easily copy a struct in C with the assignment operator (=). Although not the recommended method, you can also use memcpy() to do the same thing.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
#include <memory.h>
#include <stdint.h>
#include <stdio.h>

typedef struct {
  uint16_t value1;
  uint16_t value2;
} demoStruct_t;

int main(void) {
  demoStruct_t struct1;
  demoStruct_t struct2;

  // Copy using assignment (recommended way)
  struct2 = struct1;

  // Copy using memcpy()
  memcpy(&struct2, &struct1, sizeof(struct2));
  
  return 0;
}
WARNING

Be careful, as passing in a struct to a function will copy the entire structure, which is some cases might NOT be what you were expecting as:

  1. For a large struct, this could result in a lot of memory on the stack being used up.
  2. Any changes the function makes to the struct will not be seen from the calling function.

In these cases you what to pass in a pointer to the struct instead.

Self-referencing Structures

You can self-reference a structure, but you cannot include the structure type in the structure itself (with would cause infinite recursion). To self-reference a structure, you have to use the little-used (in C anyway) name after typedef struct.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
typedef struct cmd_t {
    // This is a legal self-reference
    cmd_t* cmdPtr;
} cmd_t;

typedef struct cmd_t {
    // This is an illegal infinite recursion error
    cmd_t cmd;
} cmd_t;

// This following declaration has got the first cmd_t
// missing. This will cause an cmd_t is undefined error.
typedef struct {
    cmd_t cmd;
} cmd_t

Further Reading

Structs are a key part of the opaque pointer design pattern.


Authors

Geoffrey Hunter

Dude making stuff.

Creative Commons License
This work is licensed under a Creative Commons Attribution 4.0 International License .

Related Content:

Tags

comments powered by Disqus