Structures and pointers
In this section, we are learning
- Creating pointer variables of a structure
- Reading and writing data with member elements using structure pointers.
Before that let’s understand some basics. Here I showed you how a structure variable is stored in the memory.
The struct DataSet is a structure definition, and in the main we created a variable, that is data.
The structure variable consumes the memory. And this output shows how exactly the member elements of this structured variable are stored in the memory. So, they are in contiguous memory locations.
In Figure 1, you can see the memory address, here the first address happens to be the base address of the structure variable. And it is also true that it happens to be the base address of the first member element.
We can see that in the first member element we stored the value 11, the same as you can see in the output. So, that proves that the base address of a structure variable is nothing but the address of the first member element.
Let’s say you have been given the base address of a structure variable and asked to change the member element values, what would you do?
You have to change the member element values using the base address of the structure variable. This is very important to understand the structure pointers.
How do you do it?
Let’s try writing some piece of code.
uint8_t *ptr = (uint8_t*)&data;
You have given the address of the structure variable, so let’s consider &data.
Where do you store this address?
Create one pointer variable. Consider the basic primitive pointer type, that is uint8_t. So, let’s create a pointer ptr = &data. This is not a valid syntax so we have to typecast here.
Modify the first element
Let’s modify the first element. Because I got the address here.
#include<stdint.h> #include<stdio.h> struct DataSet { char data1; int data2; char data3; short data4; }; int main(void) { struct DataSet data; data.data1 = 0x11; data.data2 = 0xFFFFEEEE; data.data3 = 0x22; data.data4 = 0xABCD; uint8_t *ptr = (uint8_t*)&data; //modify the first element *ptr = 0x55;
Modify the first element
This is the base address of the structure variable and which happens to be the address of the first member element. So, I can easily do this. *ptr = 0x55, which modifies the data1. So, this may work.
How about modifying the second element?
This becomes tedious. Because you don’t know how many times you have to increment this to point to the next member element. Because, in between the padding bits are there, it becomes tedious to guess.
Even if you do that, most of the time you will end up programming the wrong values into the wrong member elements. Here the easiest method is you do something like this(Figure 2).
Instead of creating a pointer variable of uint8 or uint16 etc, create a pointer variable of that struct.
struct DataSet *pData; // Here, pData is a pointer variable of type struct DataSet *.
And after that, you store the address of this structure(&data) in the pointer variable. pData is a pointer.
pData = &data; //pData now holds the address of structure variable data.
After that, you can change the value of the first member element data1 like this.
pData -> data1 = 0x55; //changing the value of data1 member element
You use that pointer variable and dereference that, select the first member element and then assign the value.
-> this is a dereferencing operator when a structure pointer is involved. You use a dot(.) operator when a non-pointer type variable is involved.
pData -> data1 = 0x55; code is equivalent to *(address_of_first_member_element_data1) = 0x55;(this code).
The meaning of pData -> data1 = 0x55; this syntax is nothing but you are dereferencing the address of the first member element and storing the value. But you need not calculate the address of the first member element, you just use this syntax.
So, you have to remember below two points.
- Use dot(.) operator when you use structure variable of non pointer type.
- Use arrow(->) operator(dereferencing operator) when you use structure variable of pointer type.
Let’s implement those 3 codes in the program, as shown below.
#include<stdint.h> #include<stdio.h> struct DataSet { char data1; int data2; char data3; short data4; }; int main(void) { struct DataSet data; data.data1 = 0x11; data.data2 = 0xFFFFEEEE; data.data3 = 0x22; data.data4 = 0xABCD; printf("Before: data.data1 = %X\n", data.data1); struct DataSet *pData; pData = &data; pData->data1 = 0x55; printf("After: data.data1 = %X\n",data.data1); getchar(); return 0; }
Print the value before and after. I used ‘%X’ to print this in hex. We modified this data1 through a pointer.
Now it should print different values.
The output is shown in Figure 3. Here we can see that the first member element data1 is indeed changed.
Some of you may be having a question like why did I change the member element values of this structure variable using pointers?
The reason is most of the time you’ll be sending the address of the structure variable to some other function, and that function then has to receive your address and it has to manipulate the member elements.
Let’s see how to do that. That is passing the address of the structure variable to some other function.
For that, let’s create one function. I call it a displayMemberElements. You are going to send the address of this struct variable to this function. This function has to receive it. So, here you need to create a structure pointer. Because the main function is going to send the address. Let’s create a struct variable to receive the pointer, struct DataSet * pdata, as shown below.
You can call this function from the main. Now you can print different member elements of this structure.
#include<stdint.h> #include<stdio.h> struct DataSet { char data1; int data2; char data3; short data4; }; void displayMemberElements(struct DataSet data); int main(void) { struct DataSet data; data.data1 = 0x11; data.data2 = 0xFFFFEEEE; data.data3 = 0x22; data.data4 = 0xABCD; displayMemberElements(data); getchar(); return 0; } void displayMemberElements(struct DataSet *pdata) { printf("data1 = %X\n",data.data1); printf("data2 = %X\n",data.data2); printf("data3 = %X\n",data.data3); printf("data4 = %X\n",data.data4); }
Now let’s execute this and here we can see that you can print the contents of the structure variable using pointers.
Here, the passing of this structure pointer to another function is called pass by reference, because you are sending the address of the structure. You can also pass this structure variable by value. You can also do that, and that case is very rarely used. So, the more widely used method is to send the address of the structure variable, rather than the structure itself.
FastBit Embedded Brain Academy Courses
Click here: https://fastbitlab.com/course1