简体   繁体   中英

Regarding C typedef struct

I have multiple instances of typedef struct box so box box1, box box2 etc. The members of the struct are length, width, height etc.

typedef struct 
{
    int width;
    int height;
} box;

box box1;
box box2;

How can I create a function that operates on all the width members of each box instance? My confusion is how do I pass a pointer to a typedef struct member that works across all instances of box. I know how to pass a pointer to a specific instance member like box1.width but how to pass .width and then do

box1.width=value;
box2.width=value;
box3.width=value;

within the function?

You might want to consider using an array rather than lots of separate instances, eg

typedef struct 
{
    int width;
    int height;
} Box;

Box boxes[3];                   // array of 3 boxes

for (b = 0; b < 3; b++)         // set `width` field of all boxes to `value`
    boxes[b].width = value;

Or, if you really do want to iterate over a number of distinct box variables for some reason then you can initialise an array of pointers instead, eg

 Box box1;  // 3 separate Box variables
 Box box2;
 Box box3;

 Box *boxes[3] = { &box1, &box2, &box3 };
                                 // array of pointers to box1, box2, box3

 for (b = 0; b < 3; b++)         // set `width` field of all boxes to `value`
    boxes[b]->width = value;

There's no such thing as field width in a typedef (or in a struct) to which you can attach a pointer. The field only physically exists in concrete objects of that type. So, you can't have a pointer to width of the struct. You can only have pointers to box1.width , box2.width and so on.

It is not possible to somehow write a function that would change width in all existing objects. More precisely, it is not possible to write a function that will somehow magically enumerate all existing objects of that type and change field width in them. It is your responsibility to tell your function which objects you want to change.

In any case, what are you trying to do?


If you are trying to write a "setter" function that would be run-time parametrized with the specific field to set, if can be done in C through offsets. For example

void set_value(box *box, size_t offset, int value) {
  *(int *) ((char *) box + offset) = value;
}

box box1;
box box2;
box box3;

void set_values(size_t offset, int value)
{
   set_value(&box1, offset, value);
   set_value(&box2, offset, value);
   set_value(&box3, offset, value);
}

Now calling

set_values(offset_of(box, width), 42);

will set widths in box1 , box2 and box3 to 42 , while calling

set_values(offset_of(box, height), -5);

will set heights in those objects to -5 .

But, again, it is your responsibility to make sure the function knows which objects it has to change. In the above example I just declared them as file-scope variables. In real-life cases it won't be generally possible.

It seems you are asking for pointers to members, however these are a C++ feature (they could be emulated with offsetof although you are likely to run into strict aliasing issues). Unless you are asking for a .width which affects all instances of box , without specifying a specific one. In that case, there is no answer. This would look something like this:

// C++ ahead

struct box
{
    int width;
    int height;
};

box boxes[3];

void setGlobalBoxesValue(int value, int box::*member)
{
    for(unsigned int i = 0; i < sizeof(boxes)/sizeof(boxes[0]); ++i)
        boxes[i].*member = value;
}

int main(int, char**)
{
    setGlobalBoxesValue(4, &box::width);
    setGlobalBoxesValue(3, &box::height);
    return 0;
}

The evil C offsetof variant:

// C emulation (not typesafe)

#include <stddef.h>
#include <string.h>

typedef struct
{
    int width;
    int height;
} box;

box boxes[3];

void setGlobalBoxesValue(int value, size_t memberOffset)
{
    for(unsigned int i = 0; i < sizeof(boxes)/sizeof(boxes[0]); ++i)
        memcpy((char*)(boxes+i) + memberOffset, &value, sizeof(value));
}

int main(int, char**)
{
    setGlobalBoxesValue(4, offsetof(box, width));
    setGlobalBoxesValue(3, offsetof(box, height));
    return 0;
}

If you just want to apply the same operation to multiple instances of box, put them in an array and loop over the array (an array of pointers if they are spread out in memory).

You can't pass the width field itself to a function. You can, however, pass the offset of it inside the struct. This is a "dirty" trick, sometimes used in low level programming, but I should not recommend you to use it without a very good reason.

Another option is to use macro. This is probably a bad idea too, but here's how:

#define assign(field, value) \
    do { \
        box1.field = value; \
        box2.field = value; \
        box3.field = value; \
    } while (0) 

and use it like this:

assign(width, 5);

If you don't know what are the boxes in advance, you can combine it with the array solution suggested here.

I am not sure I understand your question, but

How can I create a function that operates on all the width members of each box instance? My confusion is how do I pass a pointer to a typedef struct member that works across all instances of box. I know how to pass a pointer to a specific instance member like box1.width but how to pass .width and then do

by creating a function that takes the typedef as an argument you can access width of the struct

void foo(box* p)
{
  p->width  .. do something
...
} 

or if you mean passing an array of box

void foo(box* p, int count)
{ 
  for (int i = 0; i < count; ++i)
  {
     p[i]->width .. do something
    ...
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM