C and C++ basics, dereference, memory operations on struct pointers

I have looked into pointers for structs and the difference between declare something as a struct and struct pointer. This is a post summarizing what I have learned through discussions with multiple friends.

We start with an easy case, ints.


int a = 5;

void * b = &a;

*a = 1;

In this case, it is easy to tell that with the get memory address operation (&), we store that memory address of a into the variable of b. The “value” of b is the memory address of a. When we do *a = 1 with the dereference operator (*) , we set the “value” stored in a to be 1. So if you print a now, it would be 1.

The problem become tricky when we deal with a struct instead of an int, shown in the following code segment (the syntax seems to be screwed up in the website, I have attached the cpp file here  structTest)


#include<vector>

#include<stdlib.h>

#include<iostream>

struct data {

int a;

int b;

char * c;

};

using namespace std;

int main(){

char * p = new char[2];

p[0] = 't'; p[1] = '\0';

data * item = new data();

item->a = 1;

item->b = 2;

item->c = "abc";

vector<data> v;

v.push_back(*item);

cout << "before v[0] a: " << v[0].a << endl;

cout << "before v[0] c: " << v[0].c << endl;

v[0].a = 5;

v[0].c = "ABC";

cout << "after v[0] a: " << v[0].a << endl;

cout << "after v[0] c: " << v[0].c << endl;

cout << "after item a: " << item->a << endl;

cout << "after item c: " << item->c << endl;

}

The output would look like the following

before v[0] a: 1

before v[0] c: abc

after v[0] a: 5

after v[0] c: ABC

after item a: 1

after item c: abc

The reason is when you put in *item into vector, you are making a shallow copy of the original struct. As a result, even if you modified v[0].a, the item.a field will not change. When you assign a new “ABC” to v[0].c, you are just having it store a completely different address containing “ABC”.

In some cases, if you modify the char*, you can change the original. In the following example, you will see that happening


#include<vector>

#include<stdlib.h>

#include<iostream>

struct data {

int a;

int b;

char * c;

};

using namespace std;

int main(){

char * p = new char[2];

p[0] = 't'; p[1] = '\0';

data * item = new data();

item->a = 1;

item->b = 2;

item->c = p;

vector<data> v;

v.push_back(*item);

cout << "before v[0] a: " << v[0].a << endl;

cout << "before v[0] c: " << v[0].c << endl;

v[0].a = 5;

v[0].c[0] = 'A';

cout << "after v[0] a: " << v[0].a << endl;

cout << "after v[0] c: " << v[0].c << endl;

cout << "after item a: " << item->a << endl;

cout << "after item c: " << item->c << endl;

}

The output would look like the following

before v[0] a: 1

before v[0] c: t

after v[0] a: 5

after v[0] c: A

after item a: 1

after item c: A

In this case, we are directly modifying the content of the char array pointed to the original char array. As a result, when we modify v[0].c[0], we are also modifying item.c[0].

Note, you cannot modify v[0].c[0] in the first example, becasuse “abc” by default would be a const char*, which cannot be modified.

Cheers

Credit to Guowei for constructing and learn from the above example together. 🙂

Advertisements
This entry was posted in Tools and tagged . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s