How do I specify no padding bytes within a struct/class?
I've never done this before, so I'm asking first: how do I specify that a struct/class should have no padding at all, at the start, end, or middle? My classes have internal arrays, and specifying no padding lets users use an array of classX<T> as an array of T (just like C++11 std::complex). Complier-specific answers are OK, as long as I can use preprocessor flags to isolate them. I have a preprocessor flag that's currently set to 0 to indicate that there's no packing. I'll change it to 1 whenever I get a compiler's packing support. Daryle W.
On 06/17/2013 12:41 PM, Daryle Walker wrote:
I've never done this before, so I'm asking first: how do I specify that a struct/class should have no padding at all, at the start, end, or middle? My classes have internal arrays, and specifying no padding lets users use an array of classX<T> as an array of T (just like C++11 std::complex). Complier-specific answers are OK, as long as I can use preprocessor flags to isolate them.
I have a preprocessor flag that's currently set to 0 to indicate that there's no packing. I'll change it to 1 whenever I get a compiler's packing support.
This will always be compiler-specific. For gcc, try the __attribute__((packed)) directive, documented here: http://gcc.gnu.org/onlinedocs/gcc/Type-Attributes.html Jason
I've never done this before, so I'm asking first: how do I specify that a struct/class should have no padding at all, at the start, end, or middle? Daryle W.
Microsoft compilers have a pragma pack for this at source level. The pragma pack needs to be applied individually to each structure. There are also Microsoft-specific compiler flags that can be used project-globally for this. But I forgot the names of those flags. It's going down a tough road, though, because of potential portability issues. Pretty much every embedded microcontroller system I have used has some kind of structure packing facility. If you don't mind, why do you want to do pack structs in the first place? Most people cringe at the thought of packing-specific code. Sincerely, Chris.
Date: Mon, 17 Jun 2013 20:16:49 +0100 From: e_float@yahoo.com
I've never done this before, so I'm asking first: how do I specify that a struct/class should have no padding at all, at the start, end, or middle? Daryle W.
Microsoft compilers have a pragma pack for this at source level. The pragma pack needs to be applied individually to each structure.
There are also Microsoft-specific compiler flags that can be used project-globally for this. But I forgot the names of those flags.
It's going down a tough road, though, because of potential portability issues.
I'm just going to have a (huge) #if/#elsif/#else chain with every compiler I can get support on.
Pretty much every embedded microcontroller system I have used has some kind of structure packing facility.
If you don't mind, why do you want to do pack structs in the first place? Most people cringe at the thought of packing-specific code.
I've read about using an array segment of complex numbers as an array of real numbers (but twice as long) for stuff like Fourier transforms. At http://en.cppreference.com/w/cpp/numeric/complex#Non-static_data_members, the effect is documented for std::complex (at least for float/double/long-double). I want to simulate the effect.
template < typename T, unsigned R >
struct complex_it {
T c[ 1ULL << R ];
};
The above class template will be standard-layout if "T" is; that mandates no starting padding. Array elements are packed. So I can do the array-segment translation only if there's no trailing padding. In contrast:
template < typename T, unsigned R > struct complex_rt;
template < typename T >
struct complex_rt
On 2013-06-17 17:30, Daryle Walker wrote:
If you don't mind, why do you want to do pack structs in the first place? Most people cringe at the thought of packing-specific code.
I've read about using an array segment of complex numbers as an array of real numbers (but twice as long) for stuff like Fourier transforms. At http://en.cppreference.com/w/cpp/numeric/complex#Non-static_data_members, the effect is documented for std::complex (at least for float/double/long-double). I want to simulate the effect.
template < typename T, unsigned R > struct complex_it { T c[ 1ULL << R ]; };
The above class template will be standard-layout if "T" is; that mandates no starting padding. Array elements are packed. So I can do the array-segment translation only if there's no trailing padding. In contrast:
template < typename T, unsigned R > struct complex_rt;
template < typename T > struct complex_rt
{ T r; }; template < typename T, unsigned R > struct complex_rt { complex_rt
b[2]; }; will have padding all over the place if there's any trailing padding at a lower level.
I wouldn't expect any padding in such structures, because at core they're just a sequence of Ts. Perhaps you could simply verify no padding by static_assert on the size, and not worry about it unless that assertion ever fires? John Bytheway
On 17 June 2013 22:30, Daryle Walker wrote:
If you don't mind, why do you want to do pack structs in the first place? Most people cringe at the thought of packing-specific code.
I've read about using an array segment of complex numbers as an array of real numbers (but twice as long) for stuff like Fourier transforms. At http://en.cppreference.com/w/cpp/numeric/complex#Non-static_data_members, the effect is documented for std::complex (at least for float/double/long-double). I want to simulate the effect.
template < typename T, unsigned R > struct complex_it { T c[ 1ULL << R ]; };
The above class template will be standard-layout if "T" is; that mandates no starting padding. Array elements are packed. So I can do the array-segment translation only if there's no trailing padding. In contrast:
template < typename T, unsigned R > struct complex_rt;
template < typename T > struct complex_rt
{ T r; }; template < typename T, unsigned R > struct complex_rt { complex_rt
b[2]; }; will have padding all over the place if there's any trailing padding at a lower level.
But why would it have padding at a lower level?
On a sane implementation complex_rt
-----Original Message----- From: Jonathan Wakely Sent: Tuesday, June 18, 2013 5:28 AM
On 17 June 2013 22:30, Daryle Walker wrote:
template < typename T, unsigned R > struct complex_rt;
template < typename T > struct complex_rt
{ T r; }; template < typename T, unsigned R > struct complex_rt { complex_rt
b[2]; }; will have padding all over the place if there's any trailing padding at a lower level.
But why would it have padding at a lower level?
On a sane implementation complex_rt
will have the same layout as T, so an array of them will have the same layout as an array of T, ... *unless* you start dicking about with alignment and padding by overriding the compiler's decisions, at which point you might break things.
I want the code to work on non-sane implementations too, when possible. A common case that might happen is when the element size is less than a word ("char," for example). The struct may be padding-filled to reach a word boundary.
I agree that it would be better to simply use a static_assert to check the layout meets your requirements, and only force something different if needed.
I don't want a hard error. I've actually implemented a "constexpr" class constant to indicate if a particular class has padding. I was surprised that I could use an expression with "sizeof(MyClass)" within MyClass. I experimented and found out the compiler was smart about it; it won't complain when using the size of a class within that class if it's for something class-static or otherwise won't affect itself; using something like a non-static member "char x[sizeof(MyClass)]" does flag an error. Daryle W.
On 20 June 2013 06:36, Daryle Walker wrote:
-----Original Message----- From: Jonathan Wakely Sent: Tuesday, June 18, 2013 5:28 AM
On 17 June 2013 22:30, Daryle Walker wrote:
template < typename T, unsigned R > struct complex_rt;
template < typename T > struct complex_rt
{ T r; }; template < typename T, unsigned R > struct complex_rt { complex_rt
b[2]; }; will have padding all over the place if there's any trailing padding at a lower level.
But why would it have padding at a lower level?
On a sane implementation complex_rt
will have the same layout as T, so an array of them will have the same layout as an array of T, ... *unless* you start dicking about with alignment and padding by overriding the compiler's decisions, at which point you might break things. I want the code to work on non-sane implementations too, when possible. A common case that might happen is when the element size is less than a word ("char," for example). The struct may be padding-filled to reach a word boundary.
Your original mail indicated you want to turn on packed structs for all compilers that support it, not just the insane ones :-)
I agree that it would be better to simply use a static_assert to check the layout meets your requirements, and only force something different if needed.
I don't want a hard error. I've actually implemented a "constexpr" class constant to indicate if a particular class has padding. I was surprised that I could use an expression with "sizeof(MyClass)" within MyClass. I experimented and found out the compiler was smart about it; it won't complain when using the size of a class within that class if it's for something class-static or otherwise won't affect itself; using something like a non-static member "char x[sizeof(MyClass)]" does flag an error.
The hard error would let you find out which compilers need special handling, if any.
participants (5)
-
Christopher Kormanyos
-
Daryle Walker
-
Jason Roehm
-
John Bytheway
-
Jonathan Wakely