0

ok I've come across a weirdness, maybe someone can explain it. Source code is (c++ 11) :

‪#‎include‬ <stdio.h>
struct xyz_ {
    float xyz[3];
    float &x = xyz[0];
    float &y = xyz[1];
    float &z = xyz[2];
};

int main(int argc, char *argv[])
{
    xyz_ xyz;
    xyz.x = 0;
    xyz.y = 1;
    xyz.z = 2;
    xyz.xyz[1] = 1;
    printf("as array %f %f %f\n",xyz.xyz[0],xyz.xyz[1],xyz.xyz[2]);
    printf("as elements %f %f %f\n",xyz.x,xyz.y,xyz.z);
    int sizexyz = sizeof(xyz);
    int sizefloat = sizeof(float);
    printf("float is %d big, but xyz is %d big\n",sizefloat,sizexyz);
    return 0;
}

output is:

as array 0.000000 1.000000 2.000000
as elements 0.000000 1.000000 2.000000
float is 4 big, but xyz is 24 big

So the structure works as I would expect, but the size is twice as large as it should be. Using chars instead of float in the structure gives a segfault when run. I wanted to use struct xyz_ as either an array of floats or individual float elements.

iplayfast
  • 140
  • 10

5 Answers5

5

It is unspecified whether references require storage. In this case your output suggests that your compiler has decided to use storage to implement the references x, y and z.

M.M
  • 138,810
  • 21
  • 208
  • 365
2

Suppose you add another constructor:

struct xyz_ {
    float xyz[3];
    float &x = xyz[0];
    float &y = xyz[1];
    float &z = xyz[2];

    xyz_()
    {
    }

    xyz_(float& a, float& b, float& c)
        : x(a), y(b), z(c)
    {
    }
};

It should be clear that now the three x, y and z members may be bound to the array elements or may be bound to something else.

Looks like what you are looking for is

union P3d {
    float xyz[3];
    struct {
        float x, y, z;
    };
};

Unfortunately for some strange reasons (apparently mostly political) this is not supported in the standard (despite compilers do actually support it).

Community
  • 1
  • 1
6502
  • 112,025
  • 15
  • 165
  • 265
  • Yes that is what I was aiming for, I just thought that reference would be more clear. I'm going with &x() { return xyz[0] } – iplayfast Jan 09 '16 at 17:46
1

What would be the size of xyz_ if it's declared like this?

struct xyz_ {
  float xyz[3];
  float *x = &xyz[0];
  float *y = &xyz[1];
  float *z = &xyz[2];
};

The reference also needs it's own space to store the information where it is pointing at.

Inbae Jeong
  • 4,053
  • 25
  • 38
1

How about this:

struct xyz_ 
{
   float xyz[3];
   float &x() {return xyz[0];}
   float &y() {return xyz[1];}
   float &z() {return xyz[2];}
};

Not as beautiful or elegant, but might reduce the size a bit, though I think the this pointer might occupy additional space, not sure...

Of course you would have to use x(), y() and z().

Gerhard Stein
  • 1,543
  • 13
  • 25
-1

In C you could do the following, but it's not legal in C++11.

union xyz_ {
    float xyz[3];
    struct { float x, y, z; };
};
dxiv
  • 16,984
  • 2
  • 27
  • 49
  • To whoever downvoted: yes, I am well aware that it's not an answer. At the same time, it's not something that could fit into a comment, yet I believe it's pertinent to the question being asked. It's not all that unusual to mix C and C++ translation units in the same final module, sometimes for reasons of language differences like this one. – dxiv Jan 09 '16 at 07:25
  • @6502 It's not standard. See for example [Why does C++11 not support anonymous structs, while C11 does?](http://stackoverflow.com/questions/8622459/why-does-c11-not-support-anonymous-structs-while-c11-does). – dxiv Jan 09 '16 at 07:27
  • I didn't know it wasn't allowed as there are no real reasons for that (except some form of "this is not C" paranoia and "because we can decide it's not supported and you cannot say anything"). AFAIK all compilers support them however... so who cares. – 6502 Jan 09 '16 at 07:32