Structures and pointers in C
Tags: c, structures, pointers, beginners
Published: 2019-12-26 00:27:09

---
title: Structures and pointers in C
published: true
description: Working with pointers to structures in the C programming language
tags: C, structures, pointers, beginners
series: Basics of the C programming language
---

####Structures and pointers

Even if you can pass a structure as an argument to a function, passing a pointer is more efficient. The reason being, like other data structures, if a structure is passed to a function, the entire structure must be copied (remember, all C arguments are passed by value under the hood). The same is true of all other data structures. So, in general, it is best to use pointers whenever possible for efficiency's sake, since all that needs to be copied is a memory address and not the entire data structure. Using pointers with functions, is also more efficient because addresses are typically what string-handling functions are designed to work with, which makes them easier to pass them around to functions.
Another reason to use pointers is that in some older implementations of C, a structure cannot be passed as a fuction argument, but a pointer can.

The syntax to declare a pointer to a structure is much the same as for other data structures:

```c
// declare the pointer
struct date * datePtr = NULL;

// assign the pointer to the address of a strcture variable
datePtr = &todaysDate;

// use dereferencing to access any member of the date structure declared by datePtr
(*datePtr).day = 21;
// the parentheses above are required because the dot notation has higher precedence than
// the indirection operator (asterisk). This ensures that the dereferencing takes place
// before the assignment, otherwise it would try to access date with a null pointer
```

However, C has a special operator for structures pointers, `->`, the dash and greater than symbols together, which makes it much easier to dereference structures and access the variables within:

```c
#include <stdio.h>
#include <stdlib.h>

// declaring a struct outside of any function allows it to be used
// by any subsequent function, like a global variable

struct date
{
  int month;
  int day;
  int year;
};

int main (void)
{
  // create an instance of the structure called name, and the pointer variable
  struct date today, *datePtr;

  // immediately assign the pointer to point to the structure address
  datePtr = &today;

  datePtr->month = 8;
  datePtr->day = 25;
  datePtr->year = 2018;

  printf("Today's date is %i/%i/%i \n", datePtr->month, datePtr->day, datePtr->year);

  return 0;
};
```

####Structures containing pointers

A pointer can also be a member of a structure

```c

// declare a structure type intPtrs
struct intPtrs
{
  int *pointer1;
  int *pointer2;
};

// create an instance of intPtrs called myPointers
struct intPtrs myPointers;

// declare two int variables to store inside myPointers
int int1 = 100, int2;

myPointers.pointer1 = &int1;
myPointers.pointer2 = &int2;

// dereference the pointer and assign the value to int2
*myPointers.pointer2 = 97;

printf("int1: %i, *myPointers.pointer1: %i \n", int1, *myPointers.pointer1);

printf("int2: %i, *myPointers.pointer2: %i \n", int2, *myPointers.pointer2);
```

Because the above uses integers (with a known, fixed size), dynamic memory allocation is not necessary. If strings were used, then memory allocation would be used, because structures do not allocate space to store strings.

####Character arrays or character pointers?

Both of the below are valid ways to declare structures, and while there are advantages to using pointers, it is important to understand how they work with structures.

```c
struct names
{
  char firstName[20];
  char lastName[20];
}

// or

struct pnames
{
  char *first;
  char *last;
}

```

To understand the difference, see the two examples below.

```c
// create and initialize an instance of names struct
struct names veep = {"Jane", "Doe"};
```

Above, the strings are stored inside the structure.
The structure has allocated 40 bytes total to hold the names.

```c
// create and initialize an instance of the pnames struct, which contains pointers
struct pnames treas = {"Joe", "Blow"};
```

Above, the strings are stored wherever the compiler stores string constants.
The structure holds only the two _addresses_, which takes a total of 16 bytes on the example PC, so that is all that is allocated.
The structure pnames allocates no space to store strings.
It can only be used with strings that have had space allocated for them elsewhere, such as string constants or string arrays.
So, when using pointers in structures, the pointers inside should only be used to manage strings that were created and allocated elsewhere in the program.

Whenever you have pointers inside a structure, you have to use `malloc()` or `calloc()`, otherwise they will be stored wherever string constants are stored.
Use a pointer to store the address, and use a memory allocation function to allocate just the amount of memory needed for a string.

The example below shows how to allocate memory for pointers inside structures. It uses `s_gets()` to read in the user input, which is similar to `scanf`, but it will take all user input until it hits a carriage return or end-of-file character.

```c

// declare a structure called name, that holds pointers
struct name
{
  // using pointers instead of  character arrays (j.e. strings)
  char * firstName;
  char * lastName;
};

// hardcode the length of the character array so it can be passed in as a variable
const int SLEN = 50;

// declare a function getInfo that takes a pointer, and an instance
// of the structure declared in the previous example is passed in as an argument
void getInfo (struct name * pointerToNameStruct)
{
  char temp[SLEN];
  printf("Please enter your first name: ");
  s_gets(temp, SLEN);

  //allocate memory to hold name
  pointerToNameStruct->firstName = (char *) malloc(strlen(temp) + 1);

  //copy the name to allocated memory
  strcpy(pointerToNameStruct->firstName, temp);

  printf("Please enter your last name: ");
  s_gets(temp, SLEN);

  pointerToNameStruct->lastName = (char *) malloc(strlen(temp) + 1);
  strcpy(pointerToNameStruct->lastName, temp);

}
```

In the above, the two strings are not stored in the `pointerNameStruct` structure itself, just the addresses. They are stored in the block of memory that is assigned and managed by `malloc()`. The strings are read in by `s_gets`, assigned to a temporary variable with a hardcoded size, and then the only the amount of required memory is allocated `malloc()` based on the length, which is determined by `slen`.

####Recap

This subject is pretty complex, but to recap:

- Structures that contain pointers do not allocate memory to store the _data_ that is pointed to by its members, only the memory to store the addresses.
- If the pointers are of an unknown size (typically strings), then it is possible to use the structure itself to work with the data. To do so, use:
  - a temporary variable to hold the values,
  - dereferencing with the `->` symbols to access the member of the structure to work with,
  - `strlen()` to determine size,
  - a memory allocation function, e.g. `malloc()` to assign the amount of memory required, and put it in the right place in memory,
  - and `strcpy()` to copy the value from the temporary variable to the address pointed to by structure member.