C: Pointer to a struct member inside a struct

For ease of printing, I want to create one array of pointers to the elements of my structure. How can i do this? My attempt is on the last line of the structure. As a side note, this structure has different meanings than int, which are now shown here. I only want this kind of indexing for int.

struct status {
    int lastinputVac;
    int inputVac;

    int outputVac;

    /* The unit is % */
    int outputpower;

    int outputHz;

    /* The unit is % */
    int batterylevel;

    int temperatureC;

    int *ordered_values[] = { &lastinputVac, &inputVac, &outputVac, &outputpower, &outputHz, &batterylevel, &temperatureC };
}

      

+3


source to share


7 replies


Just bite the bullet and write some extra code to print it out with access to the structure membership. It's not worth compromising your design to save a few lines of code.



Imagine you need to expose this structure in a library. Do you really want to load the user with this weird array of pointers that has no real purpose?

+1


source


So the question is: "I want to create one array of pointers to the elements of my structure." and mentions that elements can be anything other than int.

I wrote a general solution that may also need a lot of improvement in terms of security or language and design consistency, but it shows one solution to the question below. The code below calculates the size of the structure, assuming the elements of the structure are the same size, and then builds an array of pointers to the elements, and the print_array function iterates through those elements, printing them out. I could overload the ostream <operator, but I wanted to keep it as simple as possible.



  #include "stdafx.h"

  struct status {
      int lastinputVac;
      int inputVac;
      int outputVac;

      /* The unit is % */
      int outputpower;

      int outputHz;

      /* The unit is % */
      int batterylevel;

      int temperatureC;
};

//template<typename T>
#include <vector>
#include <algorithm>
#include <iostream>
#include <iterator>

// hide this into a library 
template<typename T>
size_t build_array(const status& val, T*** vecptr)
{
const size_t _size = sizeof(status) / sizeof(int);
*vecptr = (T**)malloc( sizeof(T*) *_size );

for (size_t i = 0; i < _size; ++i) {
    (*vecptr)[i] = ((T *)((&val)+i));
}
return _size;
}

template<typename T>
void free_array(T** vecptr)
{
free(vecptr);
}

template<typename T>
void print_array(T **vecptr, size_t size) 
{
for (size_t i = 0; i < size; i++)
    std::cout << *(*vecptr + i) << std::endl;
}

//T1 is the type of the struct and T2 is the type of the elements
template<typename T1, typename T2>
class PrintStruct
{
private:
    T2 **m_vecptr;
    size_t m_size;

public:
    PrintStruct(T1 t) {
        m_size = build_array<T2>(t, &m_vecptr);
        print_array(m_vecptr, m_size);
    }

    ~PrintStruct() {
        free_array(m_vecptr);
    }
 };

 int _tmain(int argc, _TCHAR* argv[])
 {
 status _status;
 _status.batterylevel = 1;
 _status.inputVac = 2;
 _status.lastinputVac = 3;
 _status.outputHz = 4;
 _status.outputpower = 5;
 _status.outputVac = 6;
 _status.temperatureC = 7;

 PrintStruct<status, int> _ps(_status);
 return 0;
 }

      

+1


source


So this is not possible.

In C ++ there is the concept of member pointers ("relative" pointers), which is what you really need.

In your case and C, I would always suggest using an int array and just specifying the indices

struct status {
   int values[7];
}
..
const int lastinputVac = 0;  // or upper case when you like, or use #define
..
status a;
a.values[lastinputVac] = 27;
int z = a.values[lastinputVac];

      

Do you get an idea?

By the way, you could do both approaches with union, offering compiled access named AND in a way using array index

0


source


You cannot get the address of a struct element regardless of the instance of the struct variable; IOW, you need to do something like

struct status foo;
int *ordered_values[] = {&foo.lastInputVac, &foo.inputVac, ...};

      

However, given that all of your members are int

s, you can do some sort of punning a la

int *ordered_values = (int *) &foo;
for (i = 0; i < 7; i++)
  printf("%d\n", ordered_values[i]);

      

This should work; the address of the struct instance is the same as the address of its first member, and since all members of int

s there should be no alignment or padding issues. I don't recommend this practice, but it should work well enough for your purposes.

0


source


From reading your comments, it looks like you have a lot of elements for the structure, but you only want to print some of them. Here are my thoughts:

1) Don't put this array in a structure! It's static - it will never change for anyone struct status

, so it's wasteful and unintuitive to have it structured.

2) Have you ever thought about dividing these meanings into your own structure? Then you can use the following paradigm:

enum status {
    LASTINPUT_VAC,
    INPUT_VAC,
    OUTPUT_VAC,
    OUTPUT_PWR,
    OUTPUT_HZ,
    BATT_LVL,
    TEMPERATURE,
    STATUS_MAX
};

struct system {
    char name[MAXNAME];
    long other_data;
    float coords[2];
    char *whatever_you_have_here;
    int status[STATUS_MAX];
};

      

Then for printing / using you link to it:

struct system sys;
int temp = sys.status[TEMPERATURE];
for (int i = 0; i < STATUS_MAX; i++)
    printf("%d\n", sys.status[i]);

      

This may not suit your specific needs, but I just wanted to put it there as another way you can do this kind of thing in C. Cheers!

0


source


There is a different approach in my mind. My observation is that the members are in the correct order, but you probably want easy index access.

But a word of warning: you need to take care of the padding. padding can offset ints. However, in the case of int32, I would not expect any problems.

Some people think this is too hacky, but it is a possibility.

struct status {
  int lastinputVac;
  int inputVac;

  int outputVac;

/* The unit is % */
  int outputpower;

  int outputHz;

  /* The unit is % */
  int batterylevel;

  int temperatureC;
} stat;

int* a = &stat;

int maxIndex = (&stat.temperatureC - &stat.lastinputVac) / sizeof (stat); // should be 6
 // you could build named constants for that
a[0]; // lastinputVac
a[1]; // inputVac
a[2]; // outputVac
a[3]; // outputpower
a[4]; // outputHz
a[5]; // batterylevel
a[6]; // temperatureC

      

0


source


Combine structure with array. Check your compiler's documentation for alignment.

union {

    struct {
       int someInt0;
       int someInt1;    
    }; //anonymous

    int arry[2];

} thing;

      

~

val0 = thing.someInt0; //structure access
val1 = thing.arry[0]; //gcc, C18, XC8, and XC32 handle this with the top value indexed to 0

if (val0 == val1) { 
    puts("this works");
}

      

0


source







All Articles