How do I create a “spacer” in a C++ class memory structure?

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP











up vote
14
down vote

favorite
2












The issue



In a low level bare-metal embedded context, I would like to create a blank space in the memory, within a C++ structure and without any name, to forbid the user to access such memory location.



Right now, I have achieved to do so by putting an ugly uint32_t :96; bitfield which will conveniently take place of three words, but it will raise a warning from GCC (Bitfield too large to fit in uint32_t, which is pretty legitimate).



While it works fine, it is not very clean when you want to distribute a library with several hundreds of those warnings...



How do I do that properly?



Why is there an issue in the first place?



The project I'm working on consist in defining the memory structure of different peripherals of a whole microcontroller line (STMicroelectronics STM32). To do so, the result is a class which contains an union of several structures which defines all registers, depending on the targeted microcontroller.



One simple example is the following, for a pretty simple peripheral: a General Purpose Input/Output (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;
;
;


Where all GPIO_MAPx_YYY is a macro, defined either as uint32_t :32 or the register type (a dedicated structure).



Here you see the uint32_t :192; which works well, but trigger a warning.



I might have replaced it by several uint32_t :32; (here 6), but I have some extreme cases where I have uint32_t :1344; (42) (among others). So I would rather not add about one hundred lines on top of 8k others, even though the structure generation is scripted.



By the way, all posted code is working absolutely (and surprisingly) fine.



The exact warning message is something like this:
width of 'sool::ll::GPIO::<anonymous union>::<anonymous struct>::<anonymous>' exceeds its type (I just love how shady it is).



I would rather not solve this by simply removing the warning, but the use of



#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-WTheRightFlag"
/* My code */
#pragma GCC diagnostic pop


May be a solution... If I find TheRightFlag



In the same way as pointed out in this thread, gcc/cp/class.c hold this sad code part:



warning_at (DECL_SOURCE_LOCATION (field), 0,
"width of %qD exceeds its type", field);


Which tells us that there is no -Wxxx flag to remove this warning...










share|improve this question









New contributor




J Faucher is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.















  • 8




    have you consided char unused[12]; and so on?
    – M.M
    8 hours ago






  • 1




    This is a well done question. Good job! I'd like to know the answer myself.
    – Christopher Pisz
    8 hours ago






  • 2




    I would just suppress the warning. [class.bit]/1 guarantees the behavior of uint32_t :192;.
    – NathanOliver
    8 hours ago






  • 2




    @NathanOliver I would gladly too, but it seems that this warning is not suppressible (Using GCC) or I didn't find how to do so. Moreover, it still is not a clean way to do (but it would be pretty satisfying) . I managed to find the correct "-W" flag but didn't manage to apply it only on my own files (I don't want the user to remove this kind of warnings for his work)
    – J Faucher
    8 hours ago







  • 1




    BTW you can write :42*32 instead of :1344
    – M.M
    8 hours ago














up vote
14
down vote

favorite
2












The issue



In a low level bare-metal embedded context, I would like to create a blank space in the memory, within a C++ structure and without any name, to forbid the user to access such memory location.



Right now, I have achieved to do so by putting an ugly uint32_t :96; bitfield which will conveniently take place of three words, but it will raise a warning from GCC (Bitfield too large to fit in uint32_t, which is pretty legitimate).



While it works fine, it is not very clean when you want to distribute a library with several hundreds of those warnings...



How do I do that properly?



Why is there an issue in the first place?



The project I'm working on consist in defining the memory structure of different peripherals of a whole microcontroller line (STMicroelectronics STM32). To do so, the result is a class which contains an union of several structures which defines all registers, depending on the targeted microcontroller.



One simple example is the following, for a pretty simple peripheral: a General Purpose Input/Output (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;
;
;


Where all GPIO_MAPx_YYY is a macro, defined either as uint32_t :32 or the register type (a dedicated structure).



Here you see the uint32_t :192; which works well, but trigger a warning.



I might have replaced it by several uint32_t :32; (here 6), but I have some extreme cases where I have uint32_t :1344; (42) (among others). So I would rather not add about one hundred lines on top of 8k others, even though the structure generation is scripted.



By the way, all posted code is working absolutely (and surprisingly) fine.



The exact warning message is something like this:
width of 'sool::ll::GPIO::<anonymous union>::<anonymous struct>::<anonymous>' exceeds its type (I just love how shady it is).



I would rather not solve this by simply removing the warning, but the use of



#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-WTheRightFlag"
/* My code */
#pragma GCC diagnostic pop


May be a solution... If I find TheRightFlag



In the same way as pointed out in this thread, gcc/cp/class.c hold this sad code part:



warning_at (DECL_SOURCE_LOCATION (field), 0,
"width of %qD exceeds its type", field);


Which tells us that there is no -Wxxx flag to remove this warning...










share|improve this question









New contributor




J Faucher is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.















  • 8




    have you consided char unused[12]; and so on?
    – M.M
    8 hours ago






  • 1




    This is a well done question. Good job! I'd like to know the answer myself.
    – Christopher Pisz
    8 hours ago






  • 2




    I would just suppress the warning. [class.bit]/1 guarantees the behavior of uint32_t :192;.
    – NathanOliver
    8 hours ago






  • 2




    @NathanOliver I would gladly too, but it seems that this warning is not suppressible (Using GCC) or I didn't find how to do so. Moreover, it still is not a clean way to do (but it would be pretty satisfying) . I managed to find the correct "-W" flag but didn't manage to apply it only on my own files (I don't want the user to remove this kind of warnings for his work)
    – J Faucher
    8 hours ago







  • 1




    BTW you can write :42*32 instead of :1344
    – M.M
    8 hours ago












up vote
14
down vote

favorite
2









up vote
14
down vote

favorite
2






2





The issue



In a low level bare-metal embedded context, I would like to create a blank space in the memory, within a C++ structure and without any name, to forbid the user to access such memory location.



Right now, I have achieved to do so by putting an ugly uint32_t :96; bitfield which will conveniently take place of three words, but it will raise a warning from GCC (Bitfield too large to fit in uint32_t, which is pretty legitimate).



While it works fine, it is not very clean when you want to distribute a library with several hundreds of those warnings...



How do I do that properly?



Why is there an issue in the first place?



The project I'm working on consist in defining the memory structure of different peripherals of a whole microcontroller line (STMicroelectronics STM32). To do so, the result is a class which contains an union of several structures which defines all registers, depending on the targeted microcontroller.



One simple example is the following, for a pretty simple peripheral: a General Purpose Input/Output (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;
;
;


Where all GPIO_MAPx_YYY is a macro, defined either as uint32_t :32 or the register type (a dedicated structure).



Here you see the uint32_t :192; which works well, but trigger a warning.



I might have replaced it by several uint32_t :32; (here 6), but I have some extreme cases where I have uint32_t :1344; (42) (among others). So I would rather not add about one hundred lines on top of 8k others, even though the structure generation is scripted.



By the way, all posted code is working absolutely (and surprisingly) fine.



The exact warning message is something like this:
width of 'sool::ll::GPIO::<anonymous union>::<anonymous struct>::<anonymous>' exceeds its type (I just love how shady it is).



I would rather not solve this by simply removing the warning, but the use of



#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-WTheRightFlag"
/* My code */
#pragma GCC diagnostic pop


May be a solution... If I find TheRightFlag



In the same way as pointed out in this thread, gcc/cp/class.c hold this sad code part:



warning_at (DECL_SOURCE_LOCATION (field), 0,
"width of %qD exceeds its type", field);


Which tells us that there is no -Wxxx flag to remove this warning...










share|improve this question









New contributor




J Faucher is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.











The issue



In a low level bare-metal embedded context, I would like to create a blank space in the memory, within a C++ structure and without any name, to forbid the user to access such memory location.



Right now, I have achieved to do so by putting an ugly uint32_t :96; bitfield which will conveniently take place of three words, but it will raise a warning from GCC (Bitfield too large to fit in uint32_t, which is pretty legitimate).



While it works fine, it is not very clean when you want to distribute a library with several hundreds of those warnings...



How do I do that properly?



Why is there an issue in the first place?



The project I'm working on consist in defining the memory structure of different peripherals of a whole microcontroller line (STMicroelectronics STM32). To do so, the result is a class which contains an union of several structures which defines all registers, depending on the targeted microcontroller.



One simple example is the following, for a pretty simple peripheral: a General Purpose Input/Output (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;
;
;


Where all GPIO_MAPx_YYY is a macro, defined either as uint32_t :32 or the register type (a dedicated structure).



Here you see the uint32_t :192; which works well, but trigger a warning.



I might have replaced it by several uint32_t :32; (here 6), but I have some extreme cases where I have uint32_t :1344; (42) (among others). So I would rather not add about one hundred lines on top of 8k others, even though the structure generation is scripted.



By the way, all posted code is working absolutely (and surprisingly) fine.



The exact warning message is something like this:
width of 'sool::ll::GPIO::<anonymous union>::<anonymous struct>::<anonymous>' exceeds its type (I just love how shady it is).



I would rather not solve this by simply removing the warning, but the use of



#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-WTheRightFlag"
/* My code */
#pragma GCC diagnostic pop


May be a solution... If I find TheRightFlag



In the same way as pointed out in this thread, gcc/cp/class.c hold this sad code part:



warning_at (DECL_SOURCE_LOCATION (field), 0,
"width of %qD exceeds its type", field);


Which tells us that there is no -Wxxx flag to remove this warning...







c++ c memory-management low-level bare-metal






share|improve this question









New contributor




J Faucher is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.











share|improve this question









New contributor




J Faucher is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.









share|improve this question




share|improve this question








edited 7 mins ago









Peter Mortensen

13.2k1983111




13.2k1983111






New contributor




J Faucher is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.









asked 8 hours ago









J Faucher

713




713




New contributor




J Faucher is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.





New contributor





J Faucher is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.






J Faucher is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.







  • 8




    have you consided char unused[12]; and so on?
    – M.M
    8 hours ago






  • 1




    This is a well done question. Good job! I'd like to know the answer myself.
    – Christopher Pisz
    8 hours ago






  • 2




    I would just suppress the warning. [class.bit]/1 guarantees the behavior of uint32_t :192;.
    – NathanOliver
    8 hours ago






  • 2




    @NathanOliver I would gladly too, but it seems that this warning is not suppressible (Using GCC) or I didn't find how to do so. Moreover, it still is not a clean way to do (but it would be pretty satisfying) . I managed to find the correct "-W" flag but didn't manage to apply it only on my own files (I don't want the user to remove this kind of warnings for his work)
    – J Faucher
    8 hours ago







  • 1




    BTW you can write :42*32 instead of :1344
    – M.M
    8 hours ago












  • 8




    have you consided char unused[12]; and so on?
    – M.M
    8 hours ago






  • 1




    This is a well done question. Good job! I'd like to know the answer myself.
    – Christopher Pisz
    8 hours ago






  • 2




    I would just suppress the warning. [class.bit]/1 guarantees the behavior of uint32_t :192;.
    – NathanOliver
    8 hours ago






  • 2




    @NathanOliver I would gladly too, but it seems that this warning is not suppressible (Using GCC) or I didn't find how to do so. Moreover, it still is not a clean way to do (but it would be pretty satisfying) . I managed to find the correct "-W" flag but didn't manage to apply it only on my own files (I don't want the user to remove this kind of warnings for his work)
    – J Faucher
    8 hours ago







  • 1




    BTW you can write :42*32 instead of :1344
    – M.M
    8 hours ago







8




8




have you consided char unused[12]; and so on?
– M.M
8 hours ago




have you consided char unused[12]; and so on?
– M.M
8 hours ago




1




1




This is a well done question. Good job! I'd like to know the answer myself.
– Christopher Pisz
8 hours ago




This is a well done question. Good job! I'd like to know the answer myself.
– Christopher Pisz
8 hours ago




2




2




I would just suppress the warning. [class.bit]/1 guarantees the behavior of uint32_t :192;.
– NathanOliver
8 hours ago




I would just suppress the warning. [class.bit]/1 guarantees the behavior of uint32_t :192;.
– NathanOliver
8 hours ago




2




2




@NathanOliver I would gladly too, but it seems that this warning is not suppressible (Using GCC) or I didn't find how to do so. Moreover, it still is not a clean way to do (but it would be pretty satisfying) . I managed to find the correct "-W" flag but didn't manage to apply it only on my own files (I don't want the user to remove this kind of warnings for his work)
– J Faucher
8 hours ago





@NathanOliver I would gladly too, but it seems that this warning is not suppressible (Using GCC) or I didn't find how to do so. Moreover, it still is not a clean way to do (but it would be pretty satisfying) . I managed to find the correct "-W" flag but didn't manage to apply it only on my own files (I don't want the user to remove this kind of warnings for his work)
– J Faucher
8 hours ago





1




1




BTW you can write :42*32 instead of :1344
– M.M
8 hours ago




BTW you can write :42*32 instead of :1344
– M.M
8 hours ago












4 Answers
4






active

oldest

votes

















up vote
5
down vote













In the embedded systems arena, you can model hardware either by using a structure or by defining pointers to the register addresses.



Modeling by structure is not recommended because the compiler is allowed to add padding between members for alignment purposes (although many compilers for embedded systems have a pragma for packing the structure).



Example:



uint16_t * const UART1 = (uint16_t *)(0x40000);
const unsigned int UART_STATUS_OFFSET = 1U;
const unsigned int UART_TRANSMIT_REGISTER = 2U;
uint16_t * const UART1_STATUS_REGISTER = (UART1 + UART_STATUS_OFFSET);
uint16_t * const UART1_TRANSMIT_REGISTER = (UART1 + UART_TRANSMIT_REGISTER);


You could also use the array notation:



uint16_t status = UART1[UART_STATUS_OFFSET]; 


If you must use the structure, IMHO, the best method to skip addresses would be to define a member and not access it:



struct UART1

uint16_t status;
uint16_t reserved1; // Transmit register
uint16_t receive_register;
;


In one of our projects we have both constants and structs from different vendors (vendor 1 uses constants while vendor 2 uses structures).






share|improve this answer




















  • Thanks for your answer. However, I choose to use a structure approach to ease the work of the user when he got an auto-complete feature (You only will have the right attributes displayed) and I don't want to "show" the user the reserved slots as pointed out in a comment of my first post.
    – J Faucher
    7 hours ago










  • You can still have that by making the above address static members of a structure assuming that autocomplete is able to show static members. If not, it can be inline member functions too.
    – Phil1970
    5 hours ago










  • @JFaucher I'm not an embedded systems person and haven't tested this, but wouldn't the autocomplete issue be resolved by declaring the reserved member private? (You can declare private members in a struct, and you can use public: and private: as many times as you want, to get the correct ordering of the fields.)
    – Nathaniel
    27 mins ago


















up vote
5
down vote













How about a C++-ish way?



namespace GPIO 

static volatile uint32_t &MAP0_MODER = *reinterpret_cast<uint32_t*>(0x4000);
static volatile uint32_t &MAP0_OTYPER = *reinterpret_cast<uint32_t*>(0x4004);



int main()
GPIO::MAP0_MODER = 42;



You get autocompletion because of the GPIO namespace, and there is no need for dummy padding. Even, it is more clear what's going on, as you can see the address of each register, you don't have to rely on the compiler's padding behavior at all.






share|improve this answer






















  • Even better any other comments I have made elsewhere. That should worth more than 1 vote.
    – Phil1970
    5 hours ago










  • This might possible optimize less well than a struct for access to multiple MMIO registers from the same function. With a pointer to the base address in a register, the compiler can use load/store instructions with immediate displacements, like ldr r0, [r4, #16], while compilers are more likely to miss that optimization with each address declared separately. GCC will probably load each GPIO address into a separate register. (From a literal pool, although some of them can be represented as rotated immediates in Thumb encoding.)
    – Peter Cordes
    4 hours ago










  • @PeterCordes: I've just checked this with clang, and it optimizes this case well. I haven't checked GCC, maybe it misses this optimization as you say.
    – geza
    4 hours ago











  • Turns out my worries were unfounded; ARM GCC does optimize this way, too. godbolt.org/z/ztB7hi. But note that you want static volatile uint32_t &MAP0_MODER, not inline. An inline variable doesn't compile. (static avoids having any static storage for the pointer, and volatile is exactly what you want for MMIO to avoid dead-store elimination or optimization of write / read-back.)
    – Peter Cordes
    3 hours ago






  • 1




    @PeterCordes: inline variables is a new C++17 feature. But you're right, static does equally well for this case. Thanks for mentioning volatile, I'll add it to my answer (and change inline to static, so it works for pre C++17).
    – geza
    3 hours ago

















up vote
2
down vote













Use multiple adjacent anonymous bitfields. So instead of:



 uint32_t :160;


for example, you'd have:



 uint32_t :32;
uint32_t :32;
uint32_t :32;
uint32_t :32;
uint32_t :32;


One for each register you want to be anonymous.






share|improve this answer




















  • Thanks for the answer. I already considered that, however it would add over 200 lines on some of my files (uint32_t :1344; is in the place) so I would rather not have to go this way...
    – J Faucher
    7 hours ago

















up vote
2
down vote













To expand on Clifford's answer, you can always macro out the anonymous bitfields.



So instead of



uint32_t :160;


use



#define EMPTY_32_1 
uint32_t :32
#define EMPTY_32_2
uint32_t :32; // I guess this also can be replaced with uint64_t :64
uint32_t :32
#define EMPTY_32_3
uint32_t :32;
uint32_t :32;
uint32_t :32
#define EMPTY_UINT32(N) EMPTY_32_ ## N


And then use it like



struct A 
EMPTY_UINT32(3);
/* which resolves to EMPTY_32_3, which then resolves to real declarations */



Unfortunately, you'll need as many EMPTY_32_X variants as many bytes you have :(
Still, it allows you to have single declarations in your struct.






share|improve this answer


















  • 1




    Using Boost CPP macros, I think you can use recursion to avoid having to hand-create all the necessary macros.
    – Peter Cordes
    4 hours ago










  • You can cascade them (up to preprocessor recursion limit, but that's usually ample). So #define EMPTY_32_2 EMPTY_32_1; EMPTY_32_1 and #define EMPTY_32_3 EMPTY_32_2; EMPTY_32_1 etc.
    – Miral
    2 hours ago










Your Answer






StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");

StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);

else
createEditor();

);

function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);



);






J Faucher is a new contributor. Be nice, and check out our Code of Conduct.









 

draft saved


draft discarded


















StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53109888%2fhow-do-i-create-a-spacer-in-a-c-class-memory-structure%23new-answer', 'question_page');

);

Post as a guest






























4 Answers
4






active

oldest

votes








4 Answers
4






active

oldest

votes









active

oldest

votes






active

oldest

votes








up vote
5
down vote













In the embedded systems arena, you can model hardware either by using a structure or by defining pointers to the register addresses.



Modeling by structure is not recommended because the compiler is allowed to add padding between members for alignment purposes (although many compilers for embedded systems have a pragma for packing the structure).



Example:



uint16_t * const UART1 = (uint16_t *)(0x40000);
const unsigned int UART_STATUS_OFFSET = 1U;
const unsigned int UART_TRANSMIT_REGISTER = 2U;
uint16_t * const UART1_STATUS_REGISTER = (UART1 + UART_STATUS_OFFSET);
uint16_t * const UART1_TRANSMIT_REGISTER = (UART1 + UART_TRANSMIT_REGISTER);


You could also use the array notation:



uint16_t status = UART1[UART_STATUS_OFFSET]; 


If you must use the structure, IMHO, the best method to skip addresses would be to define a member and not access it:



struct UART1

uint16_t status;
uint16_t reserved1; // Transmit register
uint16_t receive_register;
;


In one of our projects we have both constants and structs from different vendors (vendor 1 uses constants while vendor 2 uses structures).






share|improve this answer




















  • Thanks for your answer. However, I choose to use a structure approach to ease the work of the user when he got an auto-complete feature (You only will have the right attributes displayed) and I don't want to "show" the user the reserved slots as pointed out in a comment of my first post.
    – J Faucher
    7 hours ago










  • You can still have that by making the above address static members of a structure assuming that autocomplete is able to show static members. If not, it can be inline member functions too.
    – Phil1970
    5 hours ago










  • @JFaucher I'm not an embedded systems person and haven't tested this, but wouldn't the autocomplete issue be resolved by declaring the reserved member private? (You can declare private members in a struct, and you can use public: and private: as many times as you want, to get the correct ordering of the fields.)
    – Nathaniel
    27 mins ago















up vote
5
down vote













In the embedded systems arena, you can model hardware either by using a structure or by defining pointers to the register addresses.



Modeling by structure is not recommended because the compiler is allowed to add padding between members for alignment purposes (although many compilers for embedded systems have a pragma for packing the structure).



Example:



uint16_t * const UART1 = (uint16_t *)(0x40000);
const unsigned int UART_STATUS_OFFSET = 1U;
const unsigned int UART_TRANSMIT_REGISTER = 2U;
uint16_t * const UART1_STATUS_REGISTER = (UART1 + UART_STATUS_OFFSET);
uint16_t * const UART1_TRANSMIT_REGISTER = (UART1 + UART_TRANSMIT_REGISTER);


You could also use the array notation:



uint16_t status = UART1[UART_STATUS_OFFSET]; 


If you must use the structure, IMHO, the best method to skip addresses would be to define a member and not access it:



struct UART1

uint16_t status;
uint16_t reserved1; // Transmit register
uint16_t receive_register;
;


In one of our projects we have both constants and structs from different vendors (vendor 1 uses constants while vendor 2 uses structures).






share|improve this answer




















  • Thanks for your answer. However, I choose to use a structure approach to ease the work of the user when he got an auto-complete feature (You only will have the right attributes displayed) and I don't want to "show" the user the reserved slots as pointed out in a comment of my first post.
    – J Faucher
    7 hours ago










  • You can still have that by making the above address static members of a structure assuming that autocomplete is able to show static members. If not, it can be inline member functions too.
    – Phil1970
    5 hours ago










  • @JFaucher I'm not an embedded systems person and haven't tested this, but wouldn't the autocomplete issue be resolved by declaring the reserved member private? (You can declare private members in a struct, and you can use public: and private: as many times as you want, to get the correct ordering of the fields.)
    – Nathaniel
    27 mins ago













up vote
5
down vote










up vote
5
down vote









In the embedded systems arena, you can model hardware either by using a structure or by defining pointers to the register addresses.



Modeling by structure is not recommended because the compiler is allowed to add padding between members for alignment purposes (although many compilers for embedded systems have a pragma for packing the structure).



Example:



uint16_t * const UART1 = (uint16_t *)(0x40000);
const unsigned int UART_STATUS_OFFSET = 1U;
const unsigned int UART_TRANSMIT_REGISTER = 2U;
uint16_t * const UART1_STATUS_REGISTER = (UART1 + UART_STATUS_OFFSET);
uint16_t * const UART1_TRANSMIT_REGISTER = (UART1 + UART_TRANSMIT_REGISTER);


You could also use the array notation:



uint16_t status = UART1[UART_STATUS_OFFSET]; 


If you must use the structure, IMHO, the best method to skip addresses would be to define a member and not access it:



struct UART1

uint16_t status;
uint16_t reserved1; // Transmit register
uint16_t receive_register;
;


In one of our projects we have both constants and structs from different vendors (vendor 1 uses constants while vendor 2 uses structures).






share|improve this answer












In the embedded systems arena, you can model hardware either by using a structure or by defining pointers to the register addresses.



Modeling by structure is not recommended because the compiler is allowed to add padding between members for alignment purposes (although many compilers for embedded systems have a pragma for packing the structure).



Example:



uint16_t * const UART1 = (uint16_t *)(0x40000);
const unsigned int UART_STATUS_OFFSET = 1U;
const unsigned int UART_TRANSMIT_REGISTER = 2U;
uint16_t * const UART1_STATUS_REGISTER = (UART1 + UART_STATUS_OFFSET);
uint16_t * const UART1_TRANSMIT_REGISTER = (UART1 + UART_TRANSMIT_REGISTER);


You could also use the array notation:



uint16_t status = UART1[UART_STATUS_OFFSET]; 


If you must use the structure, IMHO, the best method to skip addresses would be to define a member and not access it:



struct UART1

uint16_t status;
uint16_t reserved1; // Transmit register
uint16_t receive_register;
;


In one of our projects we have both constants and structs from different vendors (vendor 1 uses constants while vendor 2 uses structures).







share|improve this answer












share|improve this answer



share|improve this answer










answered 8 hours ago









Thomas Matthews

43.5k1168119




43.5k1168119











  • Thanks for your answer. However, I choose to use a structure approach to ease the work of the user when he got an auto-complete feature (You only will have the right attributes displayed) and I don't want to "show" the user the reserved slots as pointed out in a comment of my first post.
    – J Faucher
    7 hours ago










  • You can still have that by making the above address static members of a structure assuming that autocomplete is able to show static members. If not, it can be inline member functions too.
    – Phil1970
    5 hours ago










  • @JFaucher I'm not an embedded systems person and haven't tested this, but wouldn't the autocomplete issue be resolved by declaring the reserved member private? (You can declare private members in a struct, and you can use public: and private: as many times as you want, to get the correct ordering of the fields.)
    – Nathaniel
    27 mins ago

















  • Thanks for your answer. However, I choose to use a structure approach to ease the work of the user when he got an auto-complete feature (You only will have the right attributes displayed) and I don't want to "show" the user the reserved slots as pointed out in a comment of my first post.
    – J Faucher
    7 hours ago










  • You can still have that by making the above address static members of a structure assuming that autocomplete is able to show static members. If not, it can be inline member functions too.
    – Phil1970
    5 hours ago










  • @JFaucher I'm not an embedded systems person and haven't tested this, but wouldn't the autocomplete issue be resolved by declaring the reserved member private? (You can declare private members in a struct, and you can use public: and private: as many times as you want, to get the correct ordering of the fields.)
    – Nathaniel
    27 mins ago
















Thanks for your answer. However, I choose to use a structure approach to ease the work of the user when he got an auto-complete feature (You only will have the right attributes displayed) and I don't want to "show" the user the reserved slots as pointed out in a comment of my first post.
– J Faucher
7 hours ago




Thanks for your answer. However, I choose to use a structure approach to ease the work of the user when he got an auto-complete feature (You only will have the right attributes displayed) and I don't want to "show" the user the reserved slots as pointed out in a comment of my first post.
– J Faucher
7 hours ago












You can still have that by making the above address static members of a structure assuming that autocomplete is able to show static members. If not, it can be inline member functions too.
– Phil1970
5 hours ago




You can still have that by making the above address static members of a structure assuming that autocomplete is able to show static members. If not, it can be inline member functions too.
– Phil1970
5 hours ago












@JFaucher I'm not an embedded systems person and haven't tested this, but wouldn't the autocomplete issue be resolved by declaring the reserved member private? (You can declare private members in a struct, and you can use public: and private: as many times as you want, to get the correct ordering of the fields.)
– Nathaniel
27 mins ago





@JFaucher I'm not an embedded systems person and haven't tested this, but wouldn't the autocomplete issue be resolved by declaring the reserved member private? (You can declare private members in a struct, and you can use public: and private: as many times as you want, to get the correct ordering of the fields.)
– Nathaniel
27 mins ago













up vote
5
down vote













How about a C++-ish way?



namespace GPIO 

static volatile uint32_t &MAP0_MODER = *reinterpret_cast<uint32_t*>(0x4000);
static volatile uint32_t &MAP0_OTYPER = *reinterpret_cast<uint32_t*>(0x4004);



int main()
GPIO::MAP0_MODER = 42;



You get autocompletion because of the GPIO namespace, and there is no need for dummy padding. Even, it is more clear what's going on, as you can see the address of each register, you don't have to rely on the compiler's padding behavior at all.






share|improve this answer






















  • Even better any other comments I have made elsewhere. That should worth more than 1 vote.
    – Phil1970
    5 hours ago










  • This might possible optimize less well than a struct for access to multiple MMIO registers from the same function. With a pointer to the base address in a register, the compiler can use load/store instructions with immediate displacements, like ldr r0, [r4, #16], while compilers are more likely to miss that optimization with each address declared separately. GCC will probably load each GPIO address into a separate register. (From a literal pool, although some of them can be represented as rotated immediates in Thumb encoding.)
    – Peter Cordes
    4 hours ago










  • @PeterCordes: I've just checked this with clang, and it optimizes this case well. I haven't checked GCC, maybe it misses this optimization as you say.
    – geza
    4 hours ago











  • Turns out my worries were unfounded; ARM GCC does optimize this way, too. godbolt.org/z/ztB7hi. But note that you want static volatile uint32_t &MAP0_MODER, not inline. An inline variable doesn't compile. (static avoids having any static storage for the pointer, and volatile is exactly what you want for MMIO to avoid dead-store elimination or optimization of write / read-back.)
    – Peter Cordes
    3 hours ago






  • 1




    @PeterCordes: inline variables is a new C++17 feature. But you're right, static does equally well for this case. Thanks for mentioning volatile, I'll add it to my answer (and change inline to static, so it works for pre C++17).
    – geza
    3 hours ago














up vote
5
down vote













How about a C++-ish way?



namespace GPIO 

static volatile uint32_t &MAP0_MODER = *reinterpret_cast<uint32_t*>(0x4000);
static volatile uint32_t &MAP0_OTYPER = *reinterpret_cast<uint32_t*>(0x4004);



int main()
GPIO::MAP0_MODER = 42;



You get autocompletion because of the GPIO namespace, and there is no need for dummy padding. Even, it is more clear what's going on, as you can see the address of each register, you don't have to rely on the compiler's padding behavior at all.






share|improve this answer






















  • Even better any other comments I have made elsewhere. That should worth more than 1 vote.
    – Phil1970
    5 hours ago










  • This might possible optimize less well than a struct for access to multiple MMIO registers from the same function. With a pointer to the base address in a register, the compiler can use load/store instructions with immediate displacements, like ldr r0, [r4, #16], while compilers are more likely to miss that optimization with each address declared separately. GCC will probably load each GPIO address into a separate register. (From a literal pool, although some of them can be represented as rotated immediates in Thumb encoding.)
    – Peter Cordes
    4 hours ago










  • @PeterCordes: I've just checked this with clang, and it optimizes this case well. I haven't checked GCC, maybe it misses this optimization as you say.
    – geza
    4 hours ago











  • Turns out my worries were unfounded; ARM GCC does optimize this way, too. godbolt.org/z/ztB7hi. But note that you want static volatile uint32_t &MAP0_MODER, not inline. An inline variable doesn't compile. (static avoids having any static storage for the pointer, and volatile is exactly what you want for MMIO to avoid dead-store elimination or optimization of write / read-back.)
    – Peter Cordes
    3 hours ago






  • 1




    @PeterCordes: inline variables is a new C++17 feature. But you're right, static does equally well for this case. Thanks for mentioning volatile, I'll add it to my answer (and change inline to static, so it works for pre C++17).
    – geza
    3 hours ago












up vote
5
down vote










up vote
5
down vote









How about a C++-ish way?



namespace GPIO 

static volatile uint32_t &MAP0_MODER = *reinterpret_cast<uint32_t*>(0x4000);
static volatile uint32_t &MAP0_OTYPER = *reinterpret_cast<uint32_t*>(0x4004);



int main()
GPIO::MAP0_MODER = 42;



You get autocompletion because of the GPIO namespace, and there is no need for dummy padding. Even, it is more clear what's going on, as you can see the address of each register, you don't have to rely on the compiler's padding behavior at all.






share|improve this answer














How about a C++-ish way?



namespace GPIO 

static volatile uint32_t &MAP0_MODER = *reinterpret_cast<uint32_t*>(0x4000);
static volatile uint32_t &MAP0_OTYPER = *reinterpret_cast<uint32_t*>(0x4004);



int main()
GPIO::MAP0_MODER = 42;



You get autocompletion because of the GPIO namespace, and there is no need for dummy padding. Even, it is more clear what's going on, as you can see the address of each register, you don't have to rely on the compiler's padding behavior at all.







share|improve this answer














share|improve this answer



share|improve this answer








edited 3 hours ago

























answered 5 hours ago









geza

10.7k22669




10.7k22669











  • Even better any other comments I have made elsewhere. That should worth more than 1 vote.
    – Phil1970
    5 hours ago










  • This might possible optimize less well than a struct for access to multiple MMIO registers from the same function. With a pointer to the base address in a register, the compiler can use load/store instructions with immediate displacements, like ldr r0, [r4, #16], while compilers are more likely to miss that optimization with each address declared separately. GCC will probably load each GPIO address into a separate register. (From a literal pool, although some of them can be represented as rotated immediates in Thumb encoding.)
    – Peter Cordes
    4 hours ago










  • @PeterCordes: I've just checked this with clang, and it optimizes this case well. I haven't checked GCC, maybe it misses this optimization as you say.
    – geza
    4 hours ago











  • Turns out my worries were unfounded; ARM GCC does optimize this way, too. godbolt.org/z/ztB7hi. But note that you want static volatile uint32_t &MAP0_MODER, not inline. An inline variable doesn't compile. (static avoids having any static storage for the pointer, and volatile is exactly what you want for MMIO to avoid dead-store elimination or optimization of write / read-back.)
    – Peter Cordes
    3 hours ago






  • 1




    @PeterCordes: inline variables is a new C++17 feature. But you're right, static does equally well for this case. Thanks for mentioning volatile, I'll add it to my answer (and change inline to static, so it works for pre C++17).
    – geza
    3 hours ago
















  • Even better any other comments I have made elsewhere. That should worth more than 1 vote.
    – Phil1970
    5 hours ago










  • This might possible optimize less well than a struct for access to multiple MMIO registers from the same function. With a pointer to the base address in a register, the compiler can use load/store instructions with immediate displacements, like ldr r0, [r4, #16], while compilers are more likely to miss that optimization with each address declared separately. GCC will probably load each GPIO address into a separate register. (From a literal pool, although some of them can be represented as rotated immediates in Thumb encoding.)
    – Peter Cordes
    4 hours ago










  • @PeterCordes: I've just checked this with clang, and it optimizes this case well. I haven't checked GCC, maybe it misses this optimization as you say.
    – geza
    4 hours ago











  • Turns out my worries were unfounded; ARM GCC does optimize this way, too. godbolt.org/z/ztB7hi. But note that you want static volatile uint32_t &MAP0_MODER, not inline. An inline variable doesn't compile. (static avoids having any static storage for the pointer, and volatile is exactly what you want for MMIO to avoid dead-store elimination or optimization of write / read-back.)
    – Peter Cordes
    3 hours ago






  • 1




    @PeterCordes: inline variables is a new C++17 feature. But you're right, static does equally well for this case. Thanks for mentioning volatile, I'll add it to my answer (and change inline to static, so it works for pre C++17).
    – geza
    3 hours ago















Even better any other comments I have made elsewhere. That should worth more than 1 vote.
– Phil1970
5 hours ago




Even better any other comments I have made elsewhere. That should worth more than 1 vote.
– Phil1970
5 hours ago












This might possible optimize less well than a struct for access to multiple MMIO registers from the same function. With a pointer to the base address in a register, the compiler can use load/store instructions with immediate displacements, like ldr r0, [r4, #16], while compilers are more likely to miss that optimization with each address declared separately. GCC will probably load each GPIO address into a separate register. (From a literal pool, although some of them can be represented as rotated immediates in Thumb encoding.)
– Peter Cordes
4 hours ago




This might possible optimize less well than a struct for access to multiple MMIO registers from the same function. With a pointer to the base address in a register, the compiler can use load/store instructions with immediate displacements, like ldr r0, [r4, #16], while compilers are more likely to miss that optimization with each address declared separately. GCC will probably load each GPIO address into a separate register. (From a literal pool, although some of them can be represented as rotated immediates in Thumb encoding.)
– Peter Cordes
4 hours ago












@PeterCordes: I've just checked this with clang, and it optimizes this case well. I haven't checked GCC, maybe it misses this optimization as you say.
– geza
4 hours ago





@PeterCordes: I've just checked this with clang, and it optimizes this case well. I haven't checked GCC, maybe it misses this optimization as you say.
– geza
4 hours ago













Turns out my worries were unfounded; ARM GCC does optimize this way, too. godbolt.org/z/ztB7hi. But note that you want static volatile uint32_t &MAP0_MODER, not inline. An inline variable doesn't compile. (static avoids having any static storage for the pointer, and volatile is exactly what you want for MMIO to avoid dead-store elimination or optimization of write / read-back.)
– Peter Cordes
3 hours ago




Turns out my worries were unfounded; ARM GCC does optimize this way, too. godbolt.org/z/ztB7hi. But note that you want static volatile uint32_t &MAP0_MODER, not inline. An inline variable doesn't compile. (static avoids having any static storage for the pointer, and volatile is exactly what you want for MMIO to avoid dead-store elimination or optimization of write / read-back.)
– Peter Cordes
3 hours ago




1




1




@PeterCordes: inline variables is a new C++17 feature. But you're right, static does equally well for this case. Thanks for mentioning volatile, I'll add it to my answer (and change inline to static, so it works for pre C++17).
– geza
3 hours ago




@PeterCordes: inline variables is a new C++17 feature. But you're right, static does equally well for this case. Thanks for mentioning volatile, I'll add it to my answer (and change inline to static, so it works for pre C++17).
– geza
3 hours ago










up vote
2
down vote













Use multiple adjacent anonymous bitfields. So instead of:



 uint32_t :160;


for example, you'd have:



 uint32_t :32;
uint32_t :32;
uint32_t :32;
uint32_t :32;
uint32_t :32;


One for each register you want to be anonymous.






share|improve this answer




















  • Thanks for the answer. I already considered that, however it would add over 200 lines on some of my files (uint32_t :1344; is in the place) so I would rather not have to go this way...
    – J Faucher
    7 hours ago














up vote
2
down vote













Use multiple adjacent anonymous bitfields. So instead of:



 uint32_t :160;


for example, you'd have:



 uint32_t :32;
uint32_t :32;
uint32_t :32;
uint32_t :32;
uint32_t :32;


One for each register you want to be anonymous.






share|improve this answer




















  • Thanks for the answer. I already considered that, however it would add over 200 lines on some of my files (uint32_t :1344; is in the place) so I would rather not have to go this way...
    – J Faucher
    7 hours ago












up vote
2
down vote










up vote
2
down vote









Use multiple adjacent anonymous bitfields. So instead of:



 uint32_t :160;


for example, you'd have:



 uint32_t :32;
uint32_t :32;
uint32_t :32;
uint32_t :32;
uint32_t :32;


One for each register you want to be anonymous.






share|improve this answer












Use multiple adjacent anonymous bitfields. So instead of:



 uint32_t :160;


for example, you'd have:



 uint32_t :32;
uint32_t :32;
uint32_t :32;
uint32_t :32;
uint32_t :32;


One for each register you want to be anonymous.







share|improve this answer












share|improve this answer



share|improve this answer










answered 7 hours ago









Clifford

57k857121




57k857121











  • Thanks for the answer. I already considered that, however it would add over 200 lines on some of my files (uint32_t :1344; is in the place) so I would rather not have to go this way...
    – J Faucher
    7 hours ago
















  • Thanks for the answer. I already considered that, however it would add over 200 lines on some of my files (uint32_t :1344; is in the place) so I would rather not have to go this way...
    – J Faucher
    7 hours ago















Thanks for the answer. I already considered that, however it would add over 200 lines on some of my files (uint32_t :1344; is in the place) so I would rather not have to go this way...
– J Faucher
7 hours ago




Thanks for the answer. I already considered that, however it would add over 200 lines on some of my files (uint32_t :1344; is in the place) so I would rather not have to go this way...
– J Faucher
7 hours ago










up vote
2
down vote













To expand on Clifford's answer, you can always macro out the anonymous bitfields.



So instead of



uint32_t :160;


use



#define EMPTY_32_1 
uint32_t :32
#define EMPTY_32_2
uint32_t :32; // I guess this also can be replaced with uint64_t :64
uint32_t :32
#define EMPTY_32_3
uint32_t :32;
uint32_t :32;
uint32_t :32
#define EMPTY_UINT32(N) EMPTY_32_ ## N


And then use it like



struct A 
EMPTY_UINT32(3);
/* which resolves to EMPTY_32_3, which then resolves to real declarations */



Unfortunately, you'll need as many EMPTY_32_X variants as many bytes you have :(
Still, it allows you to have single declarations in your struct.






share|improve this answer


















  • 1




    Using Boost CPP macros, I think you can use recursion to avoid having to hand-create all the necessary macros.
    – Peter Cordes
    4 hours ago










  • You can cascade them (up to preprocessor recursion limit, but that's usually ample). So #define EMPTY_32_2 EMPTY_32_1; EMPTY_32_1 and #define EMPTY_32_3 EMPTY_32_2; EMPTY_32_1 etc.
    – Miral
    2 hours ago














up vote
2
down vote













To expand on Clifford's answer, you can always macro out the anonymous bitfields.



So instead of



uint32_t :160;


use



#define EMPTY_32_1 
uint32_t :32
#define EMPTY_32_2
uint32_t :32; // I guess this also can be replaced with uint64_t :64
uint32_t :32
#define EMPTY_32_3
uint32_t :32;
uint32_t :32;
uint32_t :32
#define EMPTY_UINT32(N) EMPTY_32_ ## N


And then use it like



struct A 
EMPTY_UINT32(3);
/* which resolves to EMPTY_32_3, which then resolves to real declarations */



Unfortunately, you'll need as many EMPTY_32_X variants as many bytes you have :(
Still, it allows you to have single declarations in your struct.






share|improve this answer


















  • 1




    Using Boost CPP macros, I think you can use recursion to avoid having to hand-create all the necessary macros.
    – Peter Cordes
    4 hours ago










  • You can cascade them (up to preprocessor recursion limit, but that's usually ample). So #define EMPTY_32_2 EMPTY_32_1; EMPTY_32_1 and #define EMPTY_32_3 EMPTY_32_2; EMPTY_32_1 etc.
    – Miral
    2 hours ago












up vote
2
down vote










up vote
2
down vote









To expand on Clifford's answer, you can always macro out the anonymous bitfields.



So instead of



uint32_t :160;


use



#define EMPTY_32_1 
uint32_t :32
#define EMPTY_32_2
uint32_t :32; // I guess this also can be replaced with uint64_t :64
uint32_t :32
#define EMPTY_32_3
uint32_t :32;
uint32_t :32;
uint32_t :32
#define EMPTY_UINT32(N) EMPTY_32_ ## N


And then use it like



struct A 
EMPTY_UINT32(3);
/* which resolves to EMPTY_32_3, which then resolves to real declarations */



Unfortunately, you'll need as many EMPTY_32_X variants as many bytes you have :(
Still, it allows you to have single declarations in your struct.






share|improve this answer














To expand on Clifford's answer, you can always macro out the anonymous bitfields.



So instead of



uint32_t :160;


use



#define EMPTY_32_1 
uint32_t :32
#define EMPTY_32_2
uint32_t :32; // I guess this also can be replaced with uint64_t :64
uint32_t :32
#define EMPTY_32_3
uint32_t :32;
uint32_t :32;
uint32_t :32
#define EMPTY_UINT32(N) EMPTY_32_ ## N


And then use it like



struct A 
EMPTY_UINT32(3);
/* which resolves to EMPTY_32_3, which then resolves to real declarations */



Unfortunately, you'll need as many EMPTY_32_X variants as many bytes you have :(
Still, it allows you to have single declarations in your struct.







share|improve this answer














share|improve this answer



share|improve this answer








edited 3 hours ago

























answered 5 hours ago









Adam Kotwasinski

1,664521




1,664521







  • 1




    Using Boost CPP macros, I think you can use recursion to avoid having to hand-create all the necessary macros.
    – Peter Cordes
    4 hours ago










  • You can cascade them (up to preprocessor recursion limit, but that's usually ample). So #define EMPTY_32_2 EMPTY_32_1; EMPTY_32_1 and #define EMPTY_32_3 EMPTY_32_2; EMPTY_32_1 etc.
    – Miral
    2 hours ago












  • 1




    Using Boost CPP macros, I think you can use recursion to avoid having to hand-create all the necessary macros.
    – Peter Cordes
    4 hours ago










  • You can cascade them (up to preprocessor recursion limit, but that's usually ample). So #define EMPTY_32_2 EMPTY_32_1; EMPTY_32_1 and #define EMPTY_32_3 EMPTY_32_2; EMPTY_32_1 etc.
    – Miral
    2 hours ago







1




1




Using Boost CPP macros, I think you can use recursion to avoid having to hand-create all the necessary macros.
– Peter Cordes
4 hours ago




Using Boost CPP macros, I think you can use recursion to avoid having to hand-create all the necessary macros.
– Peter Cordes
4 hours ago












You can cascade them (up to preprocessor recursion limit, but that's usually ample). So #define EMPTY_32_2 EMPTY_32_1; EMPTY_32_1 and #define EMPTY_32_3 EMPTY_32_2; EMPTY_32_1 etc.
– Miral
2 hours ago




You can cascade them (up to preprocessor recursion limit, but that's usually ample). So #define EMPTY_32_2 EMPTY_32_1; EMPTY_32_1 and #define EMPTY_32_3 EMPTY_32_2; EMPTY_32_1 etc.
– Miral
2 hours ago










J Faucher is a new contributor. Be nice, and check out our Code of Conduct.









 

draft saved


draft discarded


















J Faucher is a new contributor. Be nice, and check out our Code of Conduct.












J Faucher is a new contributor. Be nice, and check out our Code of Conduct.











J Faucher is a new contributor. Be nice, and check out our Code of Conduct.













 


draft saved


draft discarded














StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53109888%2fhow-do-i-create-a-spacer-in-a-c-class-memory-structure%23new-answer', 'question_page');

);

Post as a guest













































































Comments

Popular posts from this blog

What does second last employer means? [closed]

Installing NextGIS Connect into QGIS 3?

One-line joke