简体   繁体   English

关于C typedef结构

[英]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结构框的多个实例,所以box box1,box box2等。该结构的成员是长,宽,高等。

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? 如何创建对每个Box实例的所有width成员进行操作的函数? My confusion is how do I pass a pointer to a typedef struct member that works across all instances of box. 我的困惑是如何将指针传递给可在box的所有实例中使用的typedef结构成员。 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这样的特定实例成员,但是如何传递.width然后执行

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变量,则可以初始化一个指针数组,例如

 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. 在typedef(或结构)中没有可以附加指针的字段width之类的东西。 The field only physically exists in concrete objects of that type. 该字段仅物理存在于该类型的具体对象中。 So, you can't have a pointer to width of the struct. 因此,您不能拥有指向结构width的指针。 You can only have pointers to box1.width , box2.width and so on. 您只能具有指​​向box1.widthbox2.width等的指针。

It is not possible to somehow write a function that would change width in all existing objects. 无法以某种方式编写会改变所有现有对象width的函数。 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. 更确切地说,不可能编写一个以某种方式神奇地枚举该类型的所有现有对象并更改其中的字段width的函数。 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. 如果您试图编写一个“ setter”函数,该函数将在运行时使用要设置的特定字段进行参数化,则可以在C中通过偏移量来完成。 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 将在调用时将box1box2box3宽度box342

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

will set heights in those objects to -5 . 将这些对象的高度设置为-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). 似乎您在索要指向成员的指针,但这是C ++的功能(尽管您可能会遇到严格的别名问题,但可以使用offsetof来模拟它们)。 Unless you are asking for a .width which affects all instances of box , without specifying a specific one. 除非您要求的.width会影响box 所有实例,而无需指定特定实例。 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 offsetof变体:

// 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. 您不能将width字段本身传递给函数。 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? 如何创建对每个Box实例的所有width成员进行操作的函数? My confusion is how do I pass a pointer to a typedef struct member that works across all instances of box. 我的困惑是如何将指针传递给可在box的所有实例中使用的typedef结构成员。 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这样的特定实例成员,但是如何传递.width然后执行

by creating a function that takes the typedef as an argument you can access width of the struct 通过创建一个将typedef作为参数的函数,您可以访问结构的宽度

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
    ...
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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