[英]Is it possible to declare an anonymous instance in an union in C++?
在使用用於裸機嵌入式系統 (STM32)的低級C++ 時,我遇到了一個具有非平凡(結構)類型的“匿名聯合成員”聲明的用例。 這樣的事情可能嗎?
我嘗試了以下類型的代碼:
struct Specialization_CR1_t
{
uint32_t a :1 ;
uint32_t :31;
};
struct CR1_t
{
union
{
struct
{
uint32_t : 1;
uint32_t b: 1;
uint32_t :30;
} ;
// Few tries...
// Specialization_CR1_t {};
// Specialization_CR1_t;
Specialization_CR1_t () ;
// Fails with "expected unqualified-id before ')'"
};
};
int main()
{
//The goal :
struct CR1_t CR1;
CR1.a = 1;
CR1.b = 0;
}
目標是避免使用CR1.<thing>.a
。 顯然,可以在union
直接匿名聲明Specialization_CR1_t
,但最終目標是能夠使用模板和tmpl_CR1_t
而不是“只是” Specialization_CR1_t
。
我知道此處顯示的內容存在潛在的內存問題。 然而,由於這是在裸機嵌入式環境中,內存結構是完全已知的,位打包得很好而且緊密,工具鏈是固定的(位域沒有問題)。
而且,由於這個結構將直接映射到內存中,我無法承受另一個變量的開銷。 我的結構的總大小必須是 32 位,寫入a
或b
必須只更改正確的位。
此致 !
ISO C11 允許在其他結構/聯合中使用匿名結構。 某些 C++ 編譯器(包括 GNU 兼容(g++、clang++)和 MSVC++)支持將其作為擴展。 GCC 手冊有一些例子。
這是 ISO C++ 中不允許的 AFAIK。 如果您使用的編譯器未實現此擴展,請參閱此答案的中間部分。
我很確定匿名聯合在這里是一個紅鯡魚,並且您在嘗試將b
聲明為具有 31 位填充和 1 個值位的 32 位對象時會遇到完全相同的問題,在任何情況下都使用該匿名結構其他上下文。
如果它在匿名工會內部是合法的,那么它在任何地方都是合法的。 (但它不是,並且在 ISO C 中任何地方都不合法。正如@Peter 在評論中指出的那樣, struct {<members>} Instance
的名稱Instance
不能省略。如果你讓它成為struct foo {<members>};
你只是在聲明一個類型,而不是一個實例。)
您可能只需要編寫一個帶有operator=
和operator bool
重載的類,您可以這樣做,因為這是 C++。
(考慮用您實際嘗試做的事情重新命名問題:用位域成員編寫一個匿名結構。)
或者,如果您需要有關包裝類的幫助,請從 XY 問題退后一步,匿名結構方法顯然已陷入死胡同(除非有一些特定於編譯器的支持),並提出一個關於編寫一個新問題的新問題方便的包裝器,將單詞中的單個位公開為整數類型。 使用供應商標頭、編譯器擴展或普通或 C++ 運算符重載。
盡管考慮到你如何使用聯合,你可以這樣做以獲得你想要的,至少沒有模板,對吧?
struct CR1bits
{
uint32_t a: 1;
uint32_t b: 1;
uint32_t :30;
};
所以也許您應該問一些關於如何將其模板化為具有某些命名位子集的不同類型名稱的問題? 也許 C 預處理器可以幫助解決這個問題,以一種更笨拙的方式仍然讓使用這些類型的代碼看起來像你想要的那樣。
GNU C++ 和 MSVC 都支持匿名結構。 這編譯和工作:
union Obj {
struct { // extension: anonymous struct
int x;
int y;
int z;
};
int elems[3];
};
a->x
或a->elems[0]
都訪問同一個對象(假設沒有填充的標准結構布局)。
顯然這是標准 ISO C11。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.