Problem
W kontekście osadzonym na niskim poziomie typu bare-metal chciałbym utworzyć w pamięci puste miejsce w ramach struktury C ++ i bez nazwy, aby uniemożliwić użytkownikowi dostęp do takiej lokalizacji w pamięci.
W tej chwili osiągnąłem to, umieszczając brzydkie pole uint32_t :96;
bitowe, które wygodnie zajmie miejsce trzech słów, ale podniesie ostrzeżenie z GCC (Bitfield zbyt duży, aby zmieścić się w uint32_t), co jest całkiem uzasadnione.
Chociaż działa dobrze, nie jest zbyt czysty, gdy chcesz rozpowszechniać bibliotekę z kilkuset takimi ostrzeżeniami ...
Jak mam to zrobić poprawnie?
Dlaczego pojawia się problem w pierwszej kolejności?
Projekt, nad którym pracuję, polega na zdefiniowaniu struktury pamięci różnych peryferiów całej linii mikrokontrolerów (STMicroelectronics STM32). W tym celu powstaje klasa, która zawiera sumę kilku struktur definiujących wszystkie rejestry w zależności od docelowego mikrokontrolera.
Prosty przykład całkiem prostego urządzenia peryferyjnego jest następujący: wejście / wyjście ogólnego przeznaczenia (GPIO)
union
{
struct
{
GPIO_MAP0_MODER;
GPIO_MAP0_OTYPER;
GPIO_MAP0_OSPEEDR;
GPIO_MAP0_PUPDR;
GPIO_MAP0_IDR;
GPIO_MAP0_ODR;
GPIO_MAP0_BSRR;
GPIO_MAP0_LCKR;
GPIO_MAP0_AFR;
GPIO_MAP0_BRR;
GPIO_MAP0_ASCR;
};
struct
{
GPIO_MAP1_CRL;
GPIO_MAP1_CRH;
GPIO_MAP1_IDR;
GPIO_MAP1_ODR;
GPIO_MAP1_BSRR;
GPIO_MAP1_BRR;
GPIO_MAP1_LCKR;
uint32_t :32;
GPIO_MAP1_AFRL;
GPIO_MAP1_AFRH;
uint32_t :64;
};
struct
{
uint32_t :192;
GPIO_MAP2_BSRRL;
GPIO_MAP2_BSRRH;
uint32_t :160;
};
};
Gdzie wszystko GPIO_MAPx_YYY
jest makrem, zdefiniowane jako uint32_t :32
lub typ rejestru (dedykowana struktura).
Tutaj widzisz, uint32_t :192;
który działa dobrze, ale wyzwala ostrzeżenie.
Co do tej pory rozważałem:
Mogłem go zastąpić kilkoma uint32_t :32;
(6 tutaj), ale mam kilka skrajnych przypadków, w których mam uint32_t :1344;
(42) (między innymi). Więc wolałbym nie dodawać około stu wierszy do 8k innych, mimo że generowanie struktury jest skryptowane.
Dokładny komunikat ostrzegawczy jest taki:
width of 'sool::ll::GPIO::<anonymous union>::<anonymous struct>::<anonymous>' exceeds its type
(po prostu uwielbiam to, jak jest podejrzane).
Wolałbym nie rozwiązywać tego przez proste usunięcie ostrzeżenia, ale użycie
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-WTheRightFlag"
/* My code */
#pragma GCC diagnostic pop
może być rozwiązaniem ... jeśli znajdę TheRightFlag
. Jednak, jak wskazano w tym wątku , gcc/cp/class.c
z tą smutną częścią kodu:
warning_at (DECL_SOURCE_LOCATION (field), 0,
"width of %qD exceeds its type", field);
Co mówi nam, że nie ma -Wxxx
flagi, która usuwałaby to ostrzeżenie ...
char unused[12];
i tak dalej?