Fundamental C - Basic Structs
Written by Harry Fairhead   
Monday, 29 April 2019
Article Index
Fundamental C - Basic Structs
Value Semantics
Pointers to Structs

The struct is perhaps the more sophisticated of the two “native” data structures that C has, the other being the array. It is true to say that with an array and a struct you can do just about anything, but to do anything safely you need to know exactly how structs work. This extract, from my new book on programming C in an IoT context, explains the basics of structs without confusion.

Fundamental C: Getting Closer To The Machine

Now available as a paperback and ebook from Amazon.

  1. About C
      Extract Dependent v Independent
                  & Undefined Behavio
  2. Getting Started With C Using NetBeans
  3. Control Structures and Data
  4. Variables
      Extract Variables 
  5. Arithmetic  and Representation
      Extract Arithmetic and Representation 
  6. Operators and Expression
      Extract Side Effects, Sequence Points And Lazy Evaluation
      First Draft of Chapter: Low Down Data
  7. Functions Scope and Lifetime
  8. Arrays
      Extract Fundamental C - Simple Arrays **NEW
  9. Strings
  10. Pointers
      Extract  Pointers, Cast & Type Punning
  11. Structs
      Extract Basic Structs 
  12. Bit Manipulation
      Extract Shifts And Rotates 
  13. Files
  14. Compiling C – Preprocessor, Compiler, Linker

Also see the companion volume: Applying C

<ASIN:1871962609>

<ASIN:1871962463>

<ASIN:1871962617>

<ASIN:1871962455>

 

Cbookcover

The Basic Struct

Structs have a slightly complicated syntax, but if you follow how they work it all makes sense. We have already met the array, which is a block of memory used to store a repeated type - i.e. an int array is a block of memory that stores one int after another. A struct is also a block of memory, but instead of being divided up into repeated copies of the same type it can be used for a fixed set of different types.

A struct is the programming equivalent of a record card with different types of data stored on it.

For example:

struct myStruct{
    char name[25];
    int  age;
};

defines a struct with a single string of 25 bytes followed by a single int of 2 or 4 bytes.

The different parts of a struct are sometimes called fields.

In the above example, struct is laid out in memory in a similar fashion to an array with name taking 25 bytes of the block of memory followed by the int. However, because different machines need to use memory aligned on particular byte boundaries, the size of the struct may not be what you expect. You have to allow for the possibility of padding bytes.

The struct declaration doesn’t allocate memory for the struct and its doesn’t create an instance of the struct that you can use. What it does is to create a struct type called myStruct, which can be used in a variable declaration just like int.

That is, to create an instance of myStruct you would use:

struct myStruct me;

where me is a variable that references a block of memory that has a 25-char array and a 2- or 4-byte int. Notice that the type is struct myStruct and not just myStruct. The name myStruct is usually called a tag. Notice that this is like the use of enum as part of the name in an enumeration.

If you want to create an instance along with the struct type declaration, you can:

struct myStruct{
    char name[25];
    int age;
} me;

Notice that this is just a standard declaration with struct myStruct being used as soon as it is declared. You can even drop the tag and use an anonymous struct to create an instance:

struct {
    char name[25];
    int age;
} me;

You can use this declaration to create multiple structs, for example:

struct {
    char name[25];
    int age;
} me, you, person;

but notice that you cannot reuse it at other points in your program as you haven’t assigned a name to the type. Both of these idioms are common in C and can be confusing unless you understand that a struct is a type.

Once we have an instance of the new struct type, we can make use of it. You access the different components of a struct, not like an array, but using the dot name notation.

So, to set the age field, use:

me.age=19;

Setting the name field is just as easy, but being a string you need to use strcpy to set it to a string literal:

strcpy(me.name,"harry");

You can use the dot notation to print any of the fields of a struct:

printf("%d %s\n",me.age,me.name);

To initialize a struct you can simply provide the values for each field when an instance of the struct is created.

For example:

struct myStruct me={“harry”,19};

the values are used to initialize the fields in the order that they are declared in the struct.

In C99 and later you can use a designated initializer:

struct myStruct me= {.age=19,.name="harry"};

and in this case the values are assigned to the named fields and they can be in any order.

At this point the main question to answer is why is a struct created in a two-stage process? Why define a struct type and then declare a variable of that type? The answer is that defining a struct can be quite complex, unlike say an array, and hence you don’t want to repeat the exact form of the struct when you want to create an instance of it. For example, we can create another instance of the struct using:

struct myStruct person1;

and then use person1 as before.

Another reason is that we often want to create an array of structs and this can be done in the usual way as struct myStruct is a type just like int.

For example:

struct myStruct people[25];

creates an array of 25 elements, each an instance of myStruct. You can access these using array and dot notation as you might expect:

people[3].age=34;

Put simply, structs are implemented as struct types to make it easier to declare multiple instances. Notice that struct types have the same scope as a variable. If you declare a struct type within a function, then it can only be used within that function. In addition a struct type cannot be used before it is declared.



Last Updated ( Monday, 27 May 2019 )