A data structure is a group of data elements. Each element inside the data structure is known as member, which can vary from types and different lengths. To declare a data structure, you use the syntax:

Main Syntax

struct type_name {
	member_type1 member_name1;
	member_type2 member_name2;
	member_type3 member_name3;
	...
} object_names;

Alternative Syntax (type name is optional)

There is also another syntax for struct, which only switches the type_name and group of data elements together. (They still work the same, but type_name no longer exists)

You’re still giving the structure to the objects. However, if you were to make another object after line 6 with the same struct, there’s no way to refer to it (use it as a type) unless you use the main syntax above.

struct {
	member_type1 member_name1;
	member_type2 member_name2;
	member_type3 member_name3;
	...
} object_names;

Member type and name follow a similar format as variables Variables and types except that they are not initially assigned to a value.

In C++, member type is a type and member name is an identifier.

For example:

struct receipt {
	int id;
	string payee;
	double total;
	boolean paid;
};
 
// Using the struct as a type
receipt invoiceOne, invoiceTwo;

In the example, it created a struct receipt, which defined the four members: id, payee, total, & paid. Using this struct, it becomes possible to refer it as a type. In line 9, it constructed a variable that follows the type receipt. With the variables invoiceOne and invoiceTwo, they become objects to the structure.

Alternatively, it is possible to assign the objects in line 6 if you were to remove line 9.

struct receipt {
	int id;
	string payee;
	double total;
	boolean paid;
} invoiceOne, invoiceTwo;

invoiceOne & invoiceTwo objects STILL maintain the same data structure.

Differentiating structure names and object names

Object names are declared with a specific structure type whereas structure name is an identifier for a group of data elements with types. There could be multiple objects declared from a single data structure.

Once objects are declared from a specific structure type, their members are accessible. Using a dot/period (.) after the object name then follow a specific member name within that same structure will retrieve the member value of that specific member name.

invoiceOne.id; // Gets the member value of id in invoiceOne
invoiceTwo.payee; // Gets the member value of payee in invoiceTwo
invoiceOne.total; // Gets the member value of total in invoiceOne
invoiceTwo.paid; // Gets the member value of paid in invoiceTwo

Here’s an example of a use case for structure:

#include <iostream>
#include <string>
#include <vector>
#include <ctime>
 
using namespace std;
 
struct membership {
	int id;
	string owner;
	double monthlyCost;
	time_t expiresOn;
};
 
void printGymMembership(membership ms) {
	cout << "========" << endl;
	cout << ms.owner << " [" << ms.id << "]" << endl;
	cout << "Monthly cost: $" << ms.monthlyCost << endl;
    
    cout << "Expires on: " << ms.expiresOn << endl;
	cout << "========" << endl;
};
 
int main() {
    time_t currentTime;
    vector<membership> listOfMs;
    
    membership ms1;
    ms1.owner = "Alejandro";
    ms1.id = listOfMs.size() + 1;
    ms1.monthlyCost = 25;
    ms1.expiresOn = time(&currentTime)  + (86400 * 30);
    
    listOfMs.push_back(ms1);
    
	printGymMembership(ms1);
	
	membership ms2;
    ms2.owner = "Sabrina";
    ms2.id = listOfMs.size() + 1;
    ms2.monthlyCost = 10;
    ms2.expiresOn = time(&currentTime)  + (86400 * 30);
    
    listOfMs.push_back(ms2);
    
    printGymMembership(ms2);
    
    return 0;
}

Throughout this example, it has become possible to assign values to the members of an object. Each member of an object serves the same functionality as variables by assigning a value with the assignment operator. When creating a struct membership, the example constructed a variable ms1 with the type membership in line 30 so that we could start filling in the values for each member (owner, id, monthlyCost, & expiresOn). And the same goes for ms2.

The key component of data structures is referring to a member of an object or the structure as a whole. Like in the example, we used membership as a type for vector and assigned a value to each member of the two membership objects (ms1 & ms2).

After assigning values to the members of the two membership objects, the example printed out the information of the members in every gym membership object.

Pointers to structures

A structure pointer is a pointer variable that stores the memory address of a structure. It allows to point to objects of the structure type. This is the syntax for the struct pointer:

struct struct_name *ptr_name;

Here’s an example:

struct Device {
	int batteryLevel;
	string name;
};
 
// Creating a struct variable
Device iPhone = {100, "16"};

If you were to create a pointer to that struct, it would be like this:

struct Device *ptr = &iPhone;
 
ptr = &iPhone;
// Same as struct Device *ptr = &iPhone;

This example shows that ptr is initialized to make a pointer to the struct Device. And ptr is assigned to the object iPhone with & (knowing that we are going to reference the object). &iPhone is a memory address.

Using that pointer, you can pass the values to the object or read the values of the object with the (->) arrow operator

#include <stdio.h>
 
ptr -> name = "14";
printf("%d", ptr -> batteryLevel);

This operator is similar to (*ptr).batteryLevel. Either syntax of the pointer operation works the same. It is not the same with *ptr.

(*ptr).batteryLevel is not the same as (*ptr.batteryLevel)

(*ptr.batteryLevel) doesn’t exist hypothetically because ptr.batteryLevel isn’t a pointer as in the structure, it is an integer type.

ExpressionWhat is evaluatedEquivalent
a.bMember b of object a
a->bMember b of object pointed to by a(*a).b
*a.bValue pointed to by member b of object a*(a.b)
imported from C++ documentation

Important Use Cases

Struct pointers are useful when:

:LiSquareCheck: You are avoiding to copy large amounts of data Program uses less memory and become more efficient

:LiSquareCheck: You want to change values inside a function Passing struct pointers to the function allows the program to change their original

Nesting structures

Structures could nest on top of each other by using a structure type as a data element type.

struct hobbies_t {
	string name;
	string description;
}
struct friends_t {
	string name;
	int age;
	hobbies_t mainHobby;
} alejandro, sakura, ophelia;
 
friends_t * p_friends = &ophelia;
Possible declarations
alejandro.namemember name of the object alejandro
sakura.mainHobbymember mainHobby of the object sakura
ophelia.mainHobby.namestring name of the member mainHobby of the object ophelia
sakura.mainHobby.descriptionstring description of the member mainHobby of the object sakura

Examples

1. Passing Struct Pointers to Functions

#include <iostream>
#include <string>
 
using namespace std;
 
struct franchise {
	string name;
	string description;
	int maxPopulation;	
};
 
void setupFranchise(struct franchise *fran) {
	fran -> name = "McDonalds";
	fran -> description = "A fast food restaurant";
	fran -> maxPopulation = 100;
};
 
void printFranchise(struct franchise *fran) {
	cout << "==================\n";
	cout << fran -> name << "\n";
	cout << "\"" << fran -> description << "\"";
	cout << "\n\nMax Population: " << fran -> maxPopulation << "\n";
	cout << "==================";
};
 
int main() {
	struct franchise mcDo;
	
	setupFranchise(&mcDo);
	printFranchise(&mcDo);
	
 
	return 0;
}

See more practice

tl;dr

  • object_of_that_struct_name.member_name accesses the member of the object for that specific structure
  • modify member values with an assignment operator
  • using structure types for member types of a structure allows nesting structures