Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pointer to member variable

Tags:

c++

The following program output is always 1 1 1. In "Inside the c++ object model" book, it is mentioned that it will give offset. The purpose is also to find out object layout. But, I am confused with the output. Used g++ 4.5.2

class Test
{
    public:
        float a;
        float b;
        float c;
};

int main()
{
    float Test::*ptr = &Test::a;
    float Test::*ptr1 = &Test::b;
    float Test::*ptr2 = &Test::c;
    cout<<ptr<<endl;
    cout<<ptr1<<endl;
    cout<<ptr2<<endl;

    return 0;
}

Output:

1
1
1

Edit(Follow up question): In the book it is mentioned that origin.y = 0 can be transformed to &origin + (Point3d::y-1) where origin is an object to Point3d and y is member variable of class Point3d. Though When I compiled it gave me compilation error.

like image 209
K.K Avatar asked Aug 19 '12 18:08

K.K


People also ask

How do you access the member variable of a pointer?

To access a member function by pointer, we have to declare a pointer to the object and initialize it (by creating the memory at runtime, yes! We can use new keyboard for this). The second step, use arrow operator -> to access the member function using the pointer to the object.

How do you use pointers to member functions?

Using a pointer-to-member-function to call a function Calling the member function on an object using a pointer-to-member-function result = (object. *pointer_name)(arguments); or calling with a pointer to the object result = (object_ptr->*pointer_name)(arguments);

How do you assign a pointer to a variable?

It is called dereferencing or indirection). To assign an address of a variable into a pointer, you need to use the address-of operator & (e.g., pNumber = &number ). On the other hand, referencing and dereferencing are done on the references implicitly.

Can pointers be class members?

A pointer to member may not point to a static member of the class, a member of reference type, or void . A pointer to a member of a class differs from a normal pointer: it has both type information for the type of the member and for the class to which the member belongs.


2 Answers

You cannot print pointers to members, but pointers to members can implicitly be converted to bool, and those can be printed, of course. The null pointer is converted to false, and all other pointers are converted to true. By default, std::cout prints false as 0 and true as 1.

like image 138
fredoverflow Avatar answered Nov 15 '22 11:11

fredoverflow


You wrote that you wanted to find the memory offset. While what FredOverflow writes is completely true, you should make an instance of your class Test if you want to know the address of a,b and c. For instance:

Test t;
float *ptr = &t.a;
float *ptr1 = &t.b;
float *ptr2 = &t.c;

On my machine this yields the following three addresses:

0x7fff564f8918
0x7fff564f891c
0x7fff564f8920

And you will notice that they are 4 bytes (or sizeof(float)) apart and that the size of a Test is 12 bytes (using sizeof(Test)). Furthermore, the address of &t is 0x7fff564f8918 the same address of &t.a. That's how the memory layout of an instance of the class Test is formed.

You can also find the offset of members of a POD type by using offsetof().

cout << offsetof(Test, a) << endl;
cout << offsetof(Test, b) << endl;
cout << offsetof(Test, c) << endl;

Yields

0
4
8

Note that offsetof(Test, b) is essentially the same as

(unsigned long long) &(((Test*) 0)->b) - (unsigned long long) (Test*) 0

Answer to your followup question:

That code will not work because of the same errors as previously mentioned. However, if you wanted to calculate the address of your y member of origin and assign it the value 0 it can be done thusly:

class Point3d {
public:
  float x, y, z;
};

Point3d origin;
origin.y = 10;

// We take the address of origin, which points to the first member, 
// then add the offset to the member y.
float *ptr = (float*) ((unsigned long long) &origin + offsetof(Point3d, y));
cout <<  "Old value: " << *ptr << endl;
*ptr = 0;
cout <<  "New value: " << *ptr << endl;

Yields the output:

Old value: 10
New value: 0

Again remember that this is only possible because Point3d is a POD type.

like image 43
Morten Kristensen Avatar answered Nov 15 '22 10:11

Morten Kristensen