How to create a âspacerâ in the C++ class memory structure?
Clash Royale CLAN TAG#URR8PPP
up vote
9
down vote
favorite
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
New contributor
 |Â
show 13 more comments
up vote
9
down vote
favorite
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
New contributor
7
have you considedchar 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 ofuint32_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
 |Â
show 13 more comments
up vote
9
down vote
favorite
up vote
9
down vote
favorite
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
New contributor
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
c++ c memory-management low-level bare-metal
New contributor
New contributor
edited 1 hour ago
New contributor
asked 3 hours ago
J Faucher
462
462
New contributor
New contributor
7
have you considedchar 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 ofuint32_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
 |Â
show 13 more comments
7
have you considedchar 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 ofuint32_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
 |Â
show 13 more comments
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).
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 addressstatic
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
add a comment |Â
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.
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
add a comment |Â
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.
Even better any other comments I have made elsewhere. That should worth more than 1 vote.
â Phil1970
7 mins ago
add a comment |Â
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.
add a comment |Â
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).
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 addressstatic
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
add a comment |Â
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).
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 addressstatic
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
add a comment |Â
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).
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).
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 addressstatic
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
add a comment |Â
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 addressstatic
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
add a comment |Â
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.
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
add a comment |Â
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.
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
add a comment |Â
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.
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.
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
add a comment |Â
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
add a comment |Â
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.
Even better any other comments I have made elsewhere. That should worth more than 1 vote.
â Phil1970
7 mins ago
add a comment |Â
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.
Even better any other comments I have made elsewhere. That should worth more than 1 vote.
â Phil1970
7 mins ago
add a comment |Â
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.
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.
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
add a comment |Â
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
add a comment |Â
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.
add a comment |Â
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.
add a comment |Â
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.
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.
answered 15 mins ago
Adam Kotwasinski
1,629521
1,629521
add a comment |Â
add a comment |Â
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.
J Faucher is a new contributor. Be nice, and check out our Code of Conduct.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
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
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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