指针魔术:指针成员的结构等等

时间:2012-06-07 15:48:56

标签: c pointers struct

我真的不知道如何给这个问题一个好头衔 - 对不起。

只知道所有这一切的目标是什么:将一个uint8_t变量指针传递给bar(),它将它设置为1或0,我可以检查它在main中的状态。我确实需要zbar(),它是一个线程,它实际上将值设置为1或0

所以我有一个地方:

struct foo_t {
    ...
    uint8_t *state;
};

主要是我跟着:

int main(void) {
     uint8_t state = 0;
     bar(&state);

     while(1) {
          if(state)
              //do something here
     }
}

这里我们还有另一个源文件中的其他地方。

void bar(uint8_t *state) {
    struct foo_t *foo;    //using malloc here - don't worry

    foo->state = state;

    zbar(foo); 

}

void zbar(struct foo_t *arg) {
    if(condition)
       arg->state = 1;
    else
       arg->state = 0;
 }

如何使这个工作? O0 zBar实际上可以访问arg结构,这根本不是问题。

请不要担心我为什么这么奇怪,它在线程等中使用。

4 个答案:

答案 0 :(得分:2)

bar()需要通过指针获取其参数。另外,如果您要检查main中的状态,则需要在调用bool后更改指向zBar

void bar(uint8_t* state) {
  struct foo_t *foo; //using malloc here - don't worry
  foo->state = *state;
  zbar(foo);
  *state = foo->state;
}

您在mainbar(&state);

中正确调用了它

请注意,此代码现在的方式是,一旦调用zbarstate将永远不会再次更改。如果您希望线程访问(和修改)状态,则需要将地址存储在struct foo中:

struct foo
{
  // ...
  uint8_t* state;
};

并改变bar

void bar(uint8_t* state) {
  struct foo_t *foo; //using malloc here - don't worry
  foo->state = state; // no dereferencing
  // zbar(foo);  // start the thread using zbar
}

void zbar(struct foo_t *arg) {
  if(condition)
    *(arg->state) = 1;
  else
    *(arg->state) = 0;
}

然后对*(foo->state)的所有更改也会更改state中的main

答案 1 :(得分:2)

我认为你的意思是void bar(uint8_t* state)

它不符合我的意图。我再次假设您希望更改state中的main变量?如果是这样,试试

struct foo_t {
    uint8_t* state; // changed this to a pointer type.
}

void bar(uint8_t* state) {
    struct foo_t *foo = blah blah;
    foo->state = state;
    zbar(foo);
}

void zbar(foo_t* arg) {
   if (condition)
       *(arg->state) = 1;
   else
       *(arg->state) = 0;
}

tihnk 这就是你要做的事情

答案 2 :(得分:2)

认为你说的是:

  • 主题1运行main,并且有一个局部变量uint8_t state
    • 它将在循环中检查此局部变量的值,期望它可以由zbar
    • 异步更新
  • 线程2运行(除其他外)zbar
    • zbar更改arg->state的值时,您希望main在线程1中查看新值

因此,首先,您需要确保arg->statemain的本地state变量实际引用内存中的相同位置。由于bar已经分配了foo_t arg,因此可能更容易制作共享副本:

int main(void) {
    foo_t *arg = bar();

    while(1) {
        if(arg->state)
            ; //do something here
    }
}

其次,您需要确保main实际看到该位置的新值:正如 infact 所说,有几件事情可以可能会阻止这一点最明显的是,在第一次调用main之后,state 永远不需要重新加载bar的值,因为它看不到任何内容可能会改变它。

这种东西本质上是不便携的;告诉我们这个平台,我们将能够提供更多信息。

答案 3 :(得分:1)

不,这不起作用。首先,它不会编译 - foo_t的{​​{1}}成员被定义为state,但您尝试在其中存储uint8_t。如果你通过让uint8_t *bar这样的话来解决这个问题,那么它仍然无效,因为尽管foo->state = *state正在传递指向bar的{​​{1}变量,它所做的只是取消引用一次并将结果放在结构中。

您可以声明mainstate成员,将foo_tuint8_t *传递到&state并将其存储在main中。或者(如果代码的结构允许)完全忘记bar并将指针从foo_t传递到foo_tstate。也就是其中之一:

main

[编辑添加:在这种情况下,您还需要在bar中声明zbar volatile,以警告编译器另一个线程可能会修改其值。]

struct foo_t { ...; uint8_t * state; ... };
void bar(uint8_t * state) { struct foo_t * foo; ...; foo->state = state; zbar(foo); ... }
void zbar(struct foo_t * arg) { ...; *(arg->state) = 1; ... }

另一个评论。 “它在线程等中使用”做一些奇怪或丑陋的事情并不是一个好理由。如果具体的原因,为什么具体你正在使用线程做的事情需要它,当然这是另一回事,当然你没有义务为你辩护这里的设计决策 - 我只是想提醒你不要将“这里是线程”作为通用许可证来做奇怪的事情。