how to form a pointer to the n'th element of an array which is a class member

R

removeps-generic

I have

struct X
{
double array[10];
};

I want to form a pointer to the 5th element of X::array. The type of
the pointer should be
"double X::*" or "double* X::*" or something along those lines.

Here is the code I tried:

struct X
{
double array[10];
double* ptr;
};

int main()
{
double (X::* junk1)[10] = &X::array; // ok

double* X::* junk2 = &X::array;
// error in all the compilers I've tried
// but if an array decays to a
// pointer to the first element of the array
// shouldn't a pointer to a an array member decay to a
// pointer to the first element of the array member?

double* X::* junk3 = &X::ptr; // ok

double* X::* junk4 = &X::array[0];
// error in all the compilers I've tried
// the X::array[0] refers to the first element of the array
// but the compiler thinks the use of X::array[0] is an error

return 0;
}
 
V

Victor Bazarov

I have

struct X
{
double array[10];
};

I want to form a pointer to the 5th element of X::array. The type of
the pointer should be
"double X::*" or "double* X::*" or something along those lines.

Here is the code I tried:

struct X
{
double array[10];
double* ptr;
};

int main()
{
double (X::* junk1)[10] = &X::array; // ok

double* X::* junk2 = &X::array;
// error in all the compilers I've tried
// but if an array decays to a
// pointer to the first element of the array
// shouldn't a pointer to a an array member decay to a
// pointer to the first element of the array member?

double* X::* junk3 = &X::ptr; // ok

double* X::* junk4 = &X::array[0];
// error in all the compilers I've tried
// the X::array[0] refers to the first element of the array
// but the compiler thinks the use of X::array[0] is an error

return 0;
}

Not sure how you'd use it. Generally, it is not possible. Just like
"an int member of A that is a member of B" in a declaration like this:

struct B {
struct A {
int a, b;
};
};

or similar. Only one level of complexity is allowed. Not "an element
of a member of", not "a member of a member of".

Just use the member_ptr/index pair.

V
 
M

Murali Krishna

Hi (removeps-generic),

Plz sepcify your name.

struct X
{
double array[10];
};

I want to form a pointer to the 5th element of X::array. The type of
the pointer should be
"double X::*" or "double* X::*" or something along those lines.
double (X::* junk1)[10] = &X::array; // ok

This works fine but I tried to assign values but I am getting
exceptions.

I have tried this way..

int main(int argc, char* argv[])
{
struct X xObj;

double X::*junk1 = (double X::*)&X::array;

double *temp = &(xObj.*junk1);

for(int i = 0; i < 10; i++)
*(temp++) = (double)i;

temp = &(xObj.*junk1);

for(i = 0; i < 10; i++)
cout << *(temp++) << endl;

return 0;
}

I think you can understand the code.

When I tried to access like as below I am getting errors.

int main(int argc, char* argv[])
{
struct X xObj;

double (X::*junk1)[10] = &X::array;

(xObj.*junk1)[0] = 1.0f; // crashes here

cout << (xObj.*junk1)[0];
return 0;
}

-- Murali Krishna
 
R

removeps-generic

Murali said:
I have tried this way..

int main(int argc, char* argv[])
{
struct X xObj;

double X::*junk1 = (double X::*)&X::array;

Interesting. The type of X::array is a member of X which is an array
of 10 doubles. But (dobule X::*) means a member of X which is a
double. I'm confused why the assignment works, but hey, it's all good
if it does!

Thanks.
 
V

Victor Bazarov

Murali said:
I have tried this way..

int main(int argc, char* argv[])
{
struct X xObj;

double X::*junk1 = (double X::*)&X::array;

Interesting. The type of X::array is a member of X which is an array
of 10 doubles. But (dobule X::*) means a member of X which is a
double. I'm confused why the assignment works, but hey, it's all good
if it does!

There is nothing "good" about it. A cast is used. The cast means
"hey, compiler, move over with your type checking, I am now in the
driving seat!". This particular version of the C-style cast is
equivalent to 'reinterpret_cast', which only works if you intend
to store the value, and not use it. Besides, it only works if the
size of the storage (the left-hand side of the assignment) is large
enough to actually keep the right-hand side. There is no guarantee
of the latter, and the former is certainly not true (since the
intend is not to simply store it but to use it somehow). With both
requirements not satisfied, you have undefined behaviour in its
finest. Whatever you get is by pure luck or by the will of the
compiler implementors (whichever you consider better). Just don't
bring this code to *our* doorstep. Such code is *not* taken
seriously in any respectable programming shop.

V
 
M

Murali Krishna

Hi,

Interesting. The type of X::array is a member of X which is an array
of 10 doubles. But (dobule X::*) means a member of X which is a
double. I'm confused why the assignment works, but hey, it's all good
if it does!

It works. I tested it.

I'll try to tell you what it does..

We generally do not write pointers this way. I mean.. I never did that.

I used to write like this..

double *pArray = &xObj.array; // Gives the address assigned in the
memory for array of xObj.

but when you write like this..
double (X::* junk1)[10] = &X::array;

or like this..
double X::*junk1 = (double X::*)&X::array;

You can see that the value is 0x000000. it took lot of time to
understand this.

next I added one more variable in the structure.
struct X
{
double array[10];
int i;
};

int X::*pInt = &X::i;

now when you try to get a pointer to i, you get 0x000050.

(8 Bytes for double * 10) = 80 base 10 = 50 base 16 (hex)

what I have understood is, it gives the offset. as double array[10] is
the first variable to start, the offset is 0 (the offset of &X::array).


so what happens when you access with X object is, it adds the offset
with the address of the object.

ex:

xObj.*pInt = 10; // *(&xObj + pInt (offset of int i)) // some thing
like this

it worked in the same way for..
double X::*junk1 = (double X::*)&X::array;
double *temp = &(xObj.*junk1);

temp got the starting address of double array[10] allocated in the
memory for xObj.
(xObj.*junk1)[0] = 1.0f; // crashes here

that's because.. pointer to member variables or functions cannot use
arithmetic operations.
(I read that in Thinking in C++). I don't know if that is the actual
reason. That's just a guess.
I'm confused why the assignment works, but hey, it's all good
if it does!
double X::*junk1 = (double X::*)&X::array;

why leave it? we must understand.

double (X::*junk1)[10] is the pointer to array of 10 doubles

double X::*junk1 is the pointer to 1 double.

ok what happens in (double X::*)&X::array;

it takes the starting address of array, when assigning, the L value
must be capable of taking one double not 10. That's why we needed type
casting.

Tell me if you have tried some thing else.

Plz write your name. I dont want to talk to a computer.

-- Murali Krishna
 
M

Murali Krishna

Victor said:
Just don't
bring this code to *our* doorstep. Such code is *not* taken
seriously in any respectable programming shop.

V

Hi, it was just a try. I really dont know how to do that. I don't say
it is the correct implementation. Plz tell how to access pointer to
member variables of an array if you know.

Thanks..

-- Murali Krishna
 
V

Victor Bazarov

Murali said:
Hi, it was just a try. I really dont know how to do that. I don't say
it is the correct implementation. Plz tell how to access pointer to
member variables of an array if you know.

You have two choices: use a pointer to double and form it from the
object that contains your array and then index it appropriately
(in this scenario no pointer to member is involved), or form a pointer
to member of the type 'array of double' and then for any object you
can access the member through the pointer to member, and then index it
as you normally would. As you've been already told, there is no C++
syntax to form "a pointer to an element of an array that is a member
of some class".

V
 
R

removeps-generic

There is nothing "good" about it. A cast is used. The cast means
"hey, compiler, move over with your type checking, I am now in the
driving seat!". This particular version of the C-style cast is
equivalent to 'reinterpret_cast', which only works if you intend
to store the value, and not use it. Besides, it only works if the
size of the storage (the left-hand side of the assignment) is large
enough to actually keep the right-hand side. There is no guarantee
of the latter, and the former is certainly not true (since the
intend is not to simply store it but to use it somehow). With both
requirements not satisfied, you have undefined behaviour in its
finest. Whatever you get is by pure luck or by the will of the
compiler implementors (whichever you consider better). Just don't
bring this code to *our* doorstep. Such code is *not* taken
seriously in any respectable programming shop.

Good point. static_cast accepts the cast operation on my compiler.

double X::*junk1 = static_cast<double X::*>(&X::array);

Does that make it any better?
 
R

removeps-generic

Victor said:
Not sure how you'd use it. Generally, it is not possible. Just like
"an int member of A that is a member of B" in a declaration like this:

struct B {
struct A {
int a, b;
};
};

or similar. Only one level of complexity is allowed. Not "an element
of a member of", not "a member of a member of".

Seems it should be possible.

struct X
{
double x0;
double x1;
double x2;
};

Here &X::x2 would be a pointer to the 3rd element of the array.

So why is it not possible with

struct X
{
double x[3];
};

I think one should be able to say &X::x[2].

Just use the member_ptr/index pair.

What do you mean?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,774
Messages
2,569,598
Members
45,156
Latest member
KetoBurnSupplement
Top