Supported in C and C++, structs provide a way to group variables of mixed data types into one element. That element is a struct (meaning structure).
There is an important distinction here as well. When you define a struct, you are defining the shape of the struct. You then use this struct (shape) to create a struct instance.
struct test_scores_t{
int midterm_1;
int midterm_2;
int final_exam;
};
struct person_t{
/* a struct can accept a mixture of unordered types */
char name[10];
int class_year;
char gender;
test_scores_t test_scores; /* a struct can be nested within a struct */
};
int main(void){
person_t Ahmed;
return 0;
}
You can define multiple variables within a struct, each with a different data type and name. When accessing the struct, the struct elements can be accessed by name.
By default, when creating a struct, you are creating the shape of the struct. Creating an instance of the struct is an additional step. The struct resembles a composite data type in a way.
Here, we declare a struct type (its shape) and include three variables. Now we have test_scores_t
that defines this new (data type) that has three int elements.
struct test_scores_t{
int midterm_1;
int midterm_2;
int final_exam;
};
Here we declare a different struct, and include an array , variables and a struct. Yes, structs can embed other structs.
struct person_t{
/* a struct can accept a mixture of unordered types */
char name[10];
int class_year;
char gender;
test_scores_t test_scores; /* a struct can be nested within a struct */
};
Note, again, that the struct created is only a "template". Here we actually create an instance of the struct person_t
called Ahmad
. Now the struct instance Ahmed
has the members: name , class_year, gender and the test scores struct which then has the midterm and final grades.
person_t Ahmed;
Once a struct instance is created, we can access its members by the dot operator.
#include <iostream>
#include<cstring>
struct person_t{ /* person_t is a struct type */
int age;
char gender;
char name[10];
};
int main(void){
person_t Ahmed; /* A new struct object of type person_t is created */
Ahmed.age = 18; /* Struct members are accessed by . (dot) character */
Ahmed.gender = 'M';
strcpy(Ahmed.name, "Ahmed");
std::cout << "Name: " << Ahmed.name << ", Age:" << Ahmed.age
<< ", Gender = " << Ahmed.gender << std::endl;
return 0;
}
Output: Name: Ahmed, Age:18, Gender = M
Here we use the function string copy to copy over the literal string to the name array. More on strings later.
strcpy(Ahmed.name, "Ahmed");
#include <iostream>
struct person_t{
int age; char gender; char name[10];
}Sara, Abdullah; /* Struct objects can be created, they are global */
void add_age(person_t &person, int age){
person.age = age;
}
void sub_routine(void);
int main(void){
person_t Ahmed; /* A a struct created here has a local scope */
add_age(Ahmed, 24);
sub_routine();
return 0;
}
void sub_routine(void){
add_age(Sara, 19); /* Global structs can be accessed here */
add_age(Abdullah, 21);
}
Output:
test
test2
We can create multiple instances of the struct after the struct declaration, separated by comma, ending with a semicolon. Note that these struct instances are global.
struct person_t{
int age; char gender; char name[10];
}Sara, Abdullah; /* Struct objects can be created, they are global */
We can pass a struct to a function. Here we pass the struct by reference, so the original struct is access directly, not a copy of it.
void add_age(person_t &person, int age){
person.age = age;
}
add_age(Ahmed, 24);
And since Sara, and Abdullah are global struct instances, they can be accessed anywhere in the file.
void sub_routine(void){
add_age(Sara, 19); /* Global structs can be accessed here */
add_age(Abdullah, 21);
}
A function can actually return a struct. Note that it will return a copy of a struct here, perhaps this may not be the most efficient way, especially if the struct is large or this function is called many times.
#include <iostream>
struct person_t{
int age; char gender; char name[10];
}Sara;
void add_age_1(person_t &person, int age){ /* Takes struct by reference */
person.age = age;
}
person_t add_age_2(person_t person, int age){ /* Takes a copy of struct, returns a struct */
person.age = age;
return person;
}
int main(void){
person_t Ahmed; /* A a struct created here has a local scope */
add_age_1(Sara, 19); /* Original object is manipulated */
Ahmed = add_age_2(Ahmed, 24); /* A copy of the original object is passed */
return 0;
}
Since the add_age_2
function returns a struct, we can copy over the returned struct to Ahmad struct. Again, this might not be the most efficient way to do it.
Next: Classes