How to create a “spacer” in the C++ class memory structure?

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











up vote
9
down vote

favorite
1












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 3 words but will raise a warning from GCC (Bitfield too large to fit in uint32_t, which is pretty legit).



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



Do someone know how to 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 MCU 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 MCU.



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.



Best regards,
Julien



Edits...



Edit 1



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



Edit 2



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.















  • 7




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






  • 1




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






  • 1




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






  • 1




    @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
    3 hours ago







  • 1




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














up vote
9
down vote

favorite
1












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 3 words but will raise a warning from GCC (Bitfield too large to fit in uint32_t, which is pretty legit).



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



Do someone know how to 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 MCU 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 MCU.



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.



Best regards,
Julien



Edits...



Edit 1



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



Edit 2



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.















  • 7




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






  • 1




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






  • 1




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






  • 1




    @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
    3 hours ago







  • 1




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












up vote
9
down vote

favorite
1









up vote
9
down vote

favorite
1






1





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 3 words but will raise a warning from GCC (Bitfield too large to fit in uint32_t, which is pretty legit).



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



Do someone know how to 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 MCU 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 MCU.



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.



Best regards,
Julien



Edits...



Edit 1



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



Edit 2



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 3 words but will raise a warning from GCC (Bitfield too large to fit in uint32_t, which is pretty legit).



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



Do someone know how to 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 MCU 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 MCU.



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.



Best regards,
Julien



Edits...



Edit 1



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



Edit 2



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 1 hour ago





















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 3 hours ago









J Faucher

462




462




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.







  • 7




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






  • 1




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






  • 1




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






  • 1




    @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
    3 hours ago







  • 1




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












  • 7




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






  • 1




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






  • 1




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






  • 1




    @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
    3 hours ago







  • 1




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







7




7




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




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




1




1




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




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




1




1




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




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




1




1




@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
3 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
3 hours ago





1




1




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




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












4 Answers
4






active

oldest

votes

















up vote
2
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
    2 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
    9 mins 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
    2 hours ago

















up vote
1
down vote













How about a C++-ish way?



namespace GPIO 

inline uint32_t &MAP0_MODER = *reinterpret_cast<uint32_t*>(0x4000);
inline 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
    7 mins ago

















up vote
1
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;
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




















    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-to-create-a-spacer-in-the-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
    2
    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
      2 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
      9 mins ago














    up vote
    2
    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
      2 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
      9 mins ago












    up vote
    2
    down vote










    up vote
    2
    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 2 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
      2 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
      9 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
      2 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
      9 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
    2 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
    2 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
    9 mins 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
    9 mins 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
      2 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
      2 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 2 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
      2 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
      2 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
    2 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
    2 hours ago










    up vote
    1
    down vote













    How about a C++-ish way?



    namespace GPIO 

    inline uint32_t &MAP0_MODER = *reinterpret_cast<uint32_t*>(0x4000);
    inline 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
      7 mins ago














    up vote
    1
    down vote













    How about a C++-ish way?



    namespace GPIO 

    inline uint32_t &MAP0_MODER = *reinterpret_cast<uint32_t*>(0x4000);
    inline 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
      7 mins ago












    up vote
    1
    down vote










    up vote
    1
    down vote









    How about a C++-ish way?



    namespace GPIO 

    inline uint32_t &MAP0_MODER = *reinterpret_cast<uint32_t*>(0x4000);
    inline 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 

    inline uint32_t &MAP0_MODER = *reinterpret_cast<uint32_t*>(0x4000);
    inline 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










    answered 32 mins ago









    geza

    10.6k22669




    10.6k22669











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
















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















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




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










    up vote
    1
    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;
    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
























      up vote
      1
      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;
      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






















        up vote
        1
        down vote










        up vote
        1
        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;
        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;
        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










        answered 15 mins ago









        Adam Kotwasinski

        1,629521




        1,629521




















            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-to-create-a-spacer-in-the-c-class-memory-structure%23new-answer', 'question_page');

            );

            Post as a guest













































































            Comments

            Popular posts from this blog

            Long meetings (6-7 hours a day): Being “babysat” by supervisor

            Is the Concept of Multiple Fantasy Races Scientifically Flawed? [closed]

            Confectionery