Accessing struct members directly

14,308

Solution 1

It looks like you are asking two questions

Is it safe to treat &test as a 3 length int arrray?

It's probably best to avoid this. This may be a defined action in the C++ standard but even if it is, it's unlikely that everyone you work with will understand what you are doing here. I believe this is not supported if you read the standard because of the potential to pad structs but I am not sure.

Is there a better way to access a member without it's name?

Yes. Try using the offsetof macro/operator. This will provide the memory offset of a particular member within a structure and will allow you to correctly position a point to that member.

size_t offset = offsetof(mystruct,c);
int* pointerToC = (int*)((char*)&someTest + offset);

Another way though would be to just take the address of c directly

int* pointerToC = &(someTest->c);

Solution 2

No you can't be sure. The compiler is free to introduce padding between structure members.

Solution 3

To add to JaredPar's answer, another option in C++ only (not in plain C) is to create a pointer-to-member object:

struct test
{
  int a, b, c;
  bool d, e;
  int f;
  long g, h;
};

int main(void)
{
  test t1, t2;

  int test::*p;  // declare p as pointing to an int member of test
  p = &test::c;  // p now points to 'c', but it's not associating with an object
  t1->*p = 3;    // sets t1.c to 3
  t2->*p = 4;    // sets t2.c to 4

  p = &test::f;
  t1->*p = 5;    // sets t1.f to 5
  t2->*p = 6;    // sets t2.f to 6
}

Solution 4

You are probably looking for the offsetof macro. This will get you the byte offset of the member. You can then manipulate the member at that offset. Note though, this macro is implementation specific. Include stddef.h to get it to work.

Solution 5

It's probably not safe and is 100% un-readable; thus making that kind of code unacceptable in real life production code.

Share:
14,308
Matěj Zábský
Author by

Matěj Zábský

Working as C# developer at Tollnet a.s. Check out my pet project - GeoGen (programmable procedural heightmap generator). My blog LinkedIn profile GitHub profile

Updated on June 04, 2022

Comments

  • Matěj Zábský
    Matěj Zábský almost 2 years

    I have a testing struct definition as follows:

    struct test{
        int a, b, c;
        bool d, e;
        int f;
        long g, h;
    };
    

    And somewhere I use it this way:

    test* t = new test;   // create the testing struct
    int* ptr = (int*) t;
    ptr[2] = 15;          // directly manipulate the third word
    cout << t->c;         // look if it really affected the third integer
    

    This works correctly on my Windows - it prints 15 as expected, but is it safe? Can I be really sure the variable is on the spot in memory I want it to be - expecially in case of such combined structs (for example f is on my compiler the fifth word, but it is a sixth variable)?

    If not, is there any other way to manipulate struct members directly without actually having struct->member construct in the code?

  • Tom
    Tom about 15 years
    @MSalters - that doesn't make sense. &(t->c) has type int*, which is not the same as using aliasing to "peek" into a structure. For example, what if (char*)&(t->c) - (char*)t isn't a multiple of sizeof(int)?
  • Agnel Kurian
    Agnel Kurian about 14 years
    Thanks a million. Did not know offsetof! Been calling myself a C++ programmer for the last 6 years.