2012-06-07 3 views
-2

У меня действительно нет подсказки, как дать этому вопросу хорошее название - извините за это.Магия указателя: структуры с указательными элементами и многое другое

Чтобы узнать, для чего цель: передать указатель переменной uint8_t в bar(), который устанавливает его в 1 или 0, что я могу проверить его состояние внутри моей основной. Мне нужно 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, это не проблема вообще.

Пожалуйста, не волнуйтесь, почему я делаю это так странно, он используется в резьбе и т.д.

+0

Ваш вопрос, как написано в настоящее время, не имеет смысла. Нет вопросов в том, что вы написали, что вы хотите от нас делать? –

+0

Я хочу передать указатель, через который я перехожу в bar() в zbar, который затем меняет значение переменной с состоянием адреса на 1 или 0, чтобы я мог считывать состояние в моей основной. Я думаю, что по всему вопросу: Как я могу получить доступ к значению переменной, которая является элементом-указателем в структуре, где я получаю указатель из struct>. < –

ответ

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 это то, что вы пытаетесь сделать

+0

aaah! Это было полезно, спасибо за вашу помощь :) и да, это то, что я хочу сделать: D –

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

Вы вызываете его правильно в main (bar(&state);)

Обратите внимание, что на пути он этот код сейчас, как только zbar называется, state больше не изменится. Если вы хотите нить доступа (и модификации), то вам необходимо будет хранить адрес в 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

+0

Я действительно редактировал свое первое сообщение, это было мое плохое , Это была опечатка. –

+0

@Tectu - см. Мое обновление – Attila

+0

Спасибо, это помогло. Все работает сейчас, как и предполагалось :) –

1

Нет, это не работает. Прежде всего, он не будет компилироваться. member определяется как uint8_t, но вы пытаетесь сохранить в нем uint8_t *. Если вы исправите это, сделав bar, скажите что-то вроде foo->state = *state, то он все равно не сработает, потому что хотя bar передается указатель на mainstate переменной, все, что он делает с ним, - это разыгрывать его один раз и поместить результат в структура.

Вы можете объявить foo_t иметь uint8_t * член, пройти &state из main в bar и хранить, что в foo_t.Или (если структура вашего кода позволяет это) забудьте про foo_t и просто передайте указатель на state от main до bar до zbar. То есть, один из них:

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

[РЕДАКТИРОВАНИЕ добавить:. В этом случае также необходимо объявить state летучие в main, чтобы предупредить компилятор, что другой поток может изменить свое значение]

или

void bar(uint8_t * state) { ...; zbar(state); ... } 
void zbar(uint8_t * state) { ...; *state = 1; ... } 

Еще одно замечание. «Он используется в потоках и т. Д.» не является хорошим оправданием для совершения чего-то странного или уродливого. Если есть причина, почему конкретно вещи, которые вы делаете с потоками, требуют этого, конечно, это другое дело, и, конечно же, вы не обязаны защищать свои проектные решения здесь - я просто хочу предупредить вы не видите «здесь быть нитями», как лицензия делать странные вещи.

+0

Я поменял позицию бара в своем первом сообщении, это была опечатка, она занимает uint8_t *. ему нужно взять структуру, потому что там есть и другие члены. Но как я могу получить доступ к фактическому состоянию, где у меня есть указатель на то, что в моей структуре? –

+0

В коде, который вы отправили, у вас нет указателя в структуре, у вас есть фактическое значение 'uint8_t' в структуре. Первый из двух вариантов, о которых я упомянул, помещает указатель в структуру и - если я правильно вас понял - достигает именно того, о чем вы просите ... за исключением того, что я только понял, что я не показал, что код в 'main' тогда должен сделать. Я отредактирую свой ответ, чтобы сделать это более ясным. –

+0

На самом деле, нет, код в 'main' выглядит так же, как сейчас. За исключением того, что если «состояние» может быть изменено в другом потоке, вы должны объявить его «volatile» в 'main':' volatile uint8_t state; '. –

2

Я думаю то, что вы говорите:

  • нить 1 проходит main и имеет локальную переменную uint8_t state
    • он проверит значение этой локальной переменной в цикл, ожидая, что он может быть обновлен асинхронно zbar
  • нить 2 пробегов (среди прочего) zbar
    • когда zbar изменяет значение arg->state, вы хотите main увидеть новое значение в потоке 1

Итак, во-первых, вы должны убедиться, что arg->state и main «s местный 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, потому что он не видит ничего, что могло бы его изменить.

Этот материал по своей природе не переносится; скажите нам платформу, и мы сможем дать больше информации.

Смежные вопросы