język c - składnia

0

Szanowni koledzy.

Mam pewien problem. Załóżmy że mamy strukturę typu:

volatile struct
{
	uint8_t button_zero;
	uint8_t button_one;
	uint8_t button_two;
	uint8_t button_three;
	uint8_t button_four;
	uint8_t button_five;
	uint8_t button_six;
	uint8_t button_seven;
	uint8_t button_eight;
	uint8_t button_nine;
	uint8_t button_arrow_left;
	uint8_t button_arrow_right;
	uint8_t button_arrow_up;
	uint8_t button_arrow_down;
	uint8_t button_arrow_enter;
	uint8_t button_esc;
} button_counter;

I załóżmy też że musi to być struktura a nie tablica.
Załóżmy również że potrzebuję odwoływać się do konkretnego pola tej struktury (czyli do któregoś z uint8_t) jednak do którego to zależy od zmiennej x i do tego pola należy załóżmy przypisać wartość y.
Przykład: jeśli zmienna x wynosi 0 to do pola button_zero należy przypisać y, jeśli zaś np. zmienna x wynosi 5 to należy y przypisać do pola button_five.
Czuję że można to osiągnąć ale brak mi jeszcze doświadczenia i nie wiem jak to składniowo zorganizować. Wymagane jest natomiast aby nie robić żadnych "switch casów" i "ifów" a żeby to zrobić jedną instrukcją (może na wskaźnikach i rzutowaniu jakoś)...
Proszę o pomoc.

0

Może unia tablicy i tej struktury?

0

Ale jak?

4
volatile struct button_counter
{
    uint8_t button_zero;
    uint8_t button_one;
    uint8_t button_two;
    uint8_t button_three;
    uint8_t button_four;
    uint8_t button_five;
    uint8_t button_six;
    uint8_t button_seven;
    uint8_t button_eight;
    uint8_t button_nine;
    uint8_t button_arrow_left;
    uint8_t button_arrow_right;
    uint8_t button_arrow_up;
    uint8_t button_arrow_down;
    uint8_t button_arrow_enter;
    uint8_t button_esc;
};

union nazwa_unii
{
  button_counter buttons;
  uint8_t tab[sizeof(button_counter)];
};

Lub:

((uint8_t *)(&button_counter))[5] = 10;
2
volatile struct
    {
    union {
        struct {
            uint8_t button_zero;
            uint8_t button_one;
            uint8_t button_two;
            uint8_t button_three;
            uint8_t button_four;
            uint8_t button_five;
            uint8_t button_six;
            uint8_t button_seven;
            uint8_t button_eight;
            uint8_t button_nine;
            uint8_t button_arrow_left;
            uint8_t button_arrow_right;
            uint8_t button_arrow_up;
            uint8_t button_arrow_down;
            uint8_t button_arrow_enter;
            uint8_t button_esc;
        };
        uint8_t arr[16];
    };
} button_counter;

https://wandbox.org/permlink/mgGvntoFDdAZgDow

0

Noż oczywista oczywistość. Panowie dziękuję!

0

Panowie może mi ktoś jeszcze powiedzieć czy takie coś:


typedef struct kind_of_press
{
	uint8_t hit : 1;
	uint8_t bounce : 1;
	uint8_t shortpress : 1;
	uint8_t longpress : 1;
	uint8_t repeatpress : 1;	
};

typedef struct
{
	union
	{
		struct kind
		{
			kind_of_press unused_one;
			kind_of_press button_arrow_up;
			kind_of_press unused_two;
			kind_of_press button_arrow_left;
			kind_of_press button_enter;
			kind_of_press button_arrow_right;
			kind_of_press unused_three;
			kind_of_press button_arrow_down;
			kind_of_press unused_four;
			kind_of_press button_seven;
			kind_of_press button_eight;
			kind_of_press button_nine;
			kind_of_press button_four;
			kind_of_press button_five;
			kind_of_press button_six;
			kind_of_press button_one;
			kind_of_press button_two;
			kind_of_press button_three;
			kind_of_press button_zero;
			kind_of_press button_dot;
			kind_of_press button_backspace;
			kind_of_press button_esc;
		};
		kind_of_press arr[(sizeof(kind) / sizeof(*kind))];
	}
} keyboard_t;

extern volatile keyboard_t keyboard;

w pliku nagłówkowym jak jest, a w skojarzonym pliku źródłowym .c jak mamy:

volatile keyboard_t keyboard;

Sprawi że rzeczywiście wszystko będzie typu volatile , czy też muszę przy każdym polu struktur i w unii napisać to słówko volatile?

I jeszcze jedno pytanie:
Czy chcąc dobrać się do danego pola powinniśmy pisać tak:

(keyboard.arr[5]).hit = 1;

czy może tak:

keyboard.arr[5]->hit = 1;

Jaka byłaby różnica w działaniu tych dwóch instrukcji które napisałem na końcu ??

2

Tylko tak:

keyboard.arr[5].hit = 1;

Różnica pomiędzy operatorem . a -> jest taka, że . wymaga obiektu, a -> działa dla wskaźnika i jest równoważne z (*ptr)..

Poza tym, wydaje mi się, że robiąc strukturę w ten sposób, ty deklarujesz typ a nie obiekt. Więc raczej składnia byłaby taka:

typedef struct
{
    kind_of_press unused_one;
    kind_of_press button_arrow_up;
    kind_of_press unused_two;
    kind_of_press button_arrow_left;
    kind_of_press button_enter;
    kind_of_press button_arrow_right;
    kind_of_press unused_three;
    kind_of_press button_arrow_down;
    kind_of_press unused_four;
    kind_of_press button_seven;
    kind_of_press button_eight;
    kind_of_press button_nine;
    kind_of_press button_four;
    kind_of_press button_five;
    kind_of_press button_six;
    kind_of_press button_one;
    kind_of_press button_two;
    kind_of_press button_three;
    kind_of_press button_zero;
    kind_of_press button_dot;
    kind_of_press button_backspace;
    kind_of_press button_esc;
} kind;

typedef struct
{
    union
    {
        kind obj;
        kind_of_press arr[sizeof(kind) / sizeof(kind_of_press)];
    }
} keyboard_t;
 
extern volatile keyboard_t keyboard;

Albo coś podobnego.

0

A z tym volatile'm muszę pisać przy każdym polu czy wystarczy że zdeklaruję tak :

volatile keyboard_t keyboard;

i czy wówczas przy każdym odwołaniu do dowolnego pola struktury procek będzie sięgał do pamięci (inaczej mówiąc nie będzie mi w żaden sposób optymalizował dostępu do pól struktury) ?

3
Adamos19 napisał(a):

i czy wówczas przy każdym odwołaniu do dowolnego pola struktury procek będzie sięgał do pamięci (inaczej mówiąc nie będzie mi w żaden sposób optymalizował dostępu do pól struktury) ?

A do czego ma służyć ten volatile? Jeżeli do synchronizacji wartości pomiędzy wątkami to zapomnij. Volatile nie gwarantuje dostępu atomicznego. Przeznaczeniem volatile jest używanie go z peryferiami zamapowanymi na pamięć wirtualną, obsługa sygnałów, rejestrów sprzętowych.
Skutkiem jego użycia jest zapobieganie zmianie kolejności instrukcji dostępu do zmiennych typu volatile ("memory reordering", coś co robi kompilator aby zoptymalizować Twój kod) przez kompilator względem innych zmiennych typu volatile. Tzn. zmienne naokoło mogą zostać zoptymalizowane, zmienna volatile nie, będzie odczytana z pamięci. ALE według standardu C++ oraz C volatile nie gwarantuje odczytu prosto z pamięci RAM. Te zmienne mogą być odczytane z pamięci podręcznej, w której mogą być stare wartości jeżeli dostęp do adresu następował w różnych corach, bo nie został wywołany mechanizm zapewniający spójność pamięci podręcznej (cache coherence).

Adamos19 napisał(a):

A z tym volatile'm muszę pisać przy każdym polu czy wystarczy że zdeklaruję tak :

volatile keyboard_t keyboard;

To zależy co będzie w strukturze keyboard. Jeżeli nie będzie tam wskaźników to wystarczy volatile, tak jak podałeś

0

Po pierwsze dziękuję za odpowiedzi.
Volatile nie ma być używane do synchronizacji pomiędzy wątkami tylko po to że zmienna tego typu będzie czytana i zmieniana zarówno w przerwaniu jak i w ściśle nieokreślonym momencie (np. kiedy dostanę dane z uarta) więc dobrze by było aby kompilator nie optymalizował niczego w tym zakresie.
Wyjaśniliście mi bardzo dużo, dziękuję, na razie mi to wystarczy.

Co do konstrukcji typu:

(sizeof(kind) / sizeof(*kind))

to istotnie to było źle. Miało to oznaczać tyle że rozmiar "arr" w uni miał się równać tyle ile było tych pól struktury w tej unii, aby to zautomatyzować postanowiłem podeprzeć się instrukcjami "sizeof" bo gdy ktoś by sobie zechciał dopisać pole struktury to rozmiar tej tablicy w unii także automatycznie by się zwiększył co umożliwiłoby w dalszym ciągu dostanie się do pól tej struktury po numerze indexu.
Rozpracowałem to wszystko dzięki Waszej pomocy. Aktualnie działa mi to tak jak chcę a zrobiłem tak:

typedef struct kind_of_press
{
	uint8_t hit : 1;
	uint8_t bounce : 1;
	uint8_t shortpress : 1;
	uint8_t longpress : 1;
	uint8_t repeatpress : 1;	
} kind_of_press_t;

typedef struct
{
	union
	{
		struct kind
		{
			kind_of_press_t unused_one;
			kind_of_press_t button_arrow_up;
			kind_of_press_t unused_two;
			kind_of_press_t button_arrow_left;
			kind_of_press_t button_enter;
			kind_of_press_t button_arrow_right;
			kind_of_press_t unused_three;
			kind_of_press_t button_arrow_down;
			kind_of_press_t unused_four;
			kind_of_press_t button_seven;
			kind_of_press_t button_eight;
			kind_of_press_t button_nine;
			kind_of_press_t button_four;
			kind_of_press_t button_five;
			kind_of_press_t button_six;
			kind_of_press_t button_one;
			kind_of_press_t button_two;
			kind_of_press_t button_three;
			kind_of_press_t button_zero;
			kind_of_press_t button_dot;
			kind_of_press_t button_backspace;
			kind_of_press_t button_esc;
		} kind_t;
		kind_of_press_t arr[22];
	};
} keyboard_t;

volatile keyboard_t keyboard;

1 użytkowników online, w tym zalogowanych: 0, gości: 1