4 ms·
> The worst that you will get is padding at the end of the structure so that if two or more of them are arrayed, the first member is correctly aligned at all th
by vonmoltke 10y ago
> The worst that you will get is padding at the end of the structure so that if two or more of them are arrayed, the first member is correctly aligned at all the array indices.
This is not guaranteed. If you want to ensure all array member starting addresses are aligned for all compilers and platforms you need to add explicit dead space. You should also be using the fixed-width numeric types.
- kazinator 10y agoIt's not guaranteed (as in "money back" or whatever). It's merely required by ISO C for conformance. If a struct is declared like this: struct foo { whatever_type_t first_member; // ... }; then an array of this type can also be declared: struct foo farray[42]; A conforming ISO C implementation has to ensure that farray[1].first_member, and farray[2].first_member, and so on, are all allocated such that they meet the alignment requirements fro whatever_type_t. It cannot be that farray[0].first_member is accessible, but farray[1].first_member throws an alignment exception or whatever. Programmers should not have to do anything to ensure this. So, if necessary, padding is added at the end of struct foo to make this alignment happen. In practice, compilers add the padding even if it's not required for at least two reasons: performance (misaligned accesses, though supported, may be slow) and compatibility (having the structure look the same across multiple architectures supported by the same compiler, at most modulo byte order). > You should also be using the fixed-width numeric types. I'm not aware that C provides any other, currently. Though you can simulate them with libraries, of course.
- david-given 10y agoI agree with you, but it'd be nicer if it were easier to figure this out from the standard --- either I'm missing something or else you have to infer it from reading between the lines: 6.7.2.1 para 15 of the C11 standard: Within a structure object, the non-bit-field members and the units in which bit-fields reside have addresses that increase in the order in which they are declared. A pointer to a structure object, suitably converted, points to its initial member (or if that member is a bit-field, then to the unit in which it resides), and vice versa. 6.7.2.1 para 17: There may be unnamed padding at the end of a structure or union. 6.2.5 para 20: An array type describes a contiguously allocated nonempty set of objects with a particular member object type, called the element type. http://www.open-std.org/jtc1/sc22/WG14/www/docs/n1570.pdf http://www.open-std.org/jtc1/sc22/WG14/www/docs/n1570.pdf So, on a platform with strict alignment, in order to achieve contiguous packing of structures (required by the last) and to achieve each structure member having a valid pointer (required by the first) the implementation must add enough optional padding (allowed by the middle) to make the size of the structure aligned. > You should also be using the fixed-width numeric types. I believe the parent is referring to the int8_t, int16_t types rather than the implementation-defined int, short, long types here.
- vonmoltke 10y ago> I agree with you, but it'd be nicer if it were easier to figure this out from the standard --- either I'm missing something or else you have to infer it from reading between the lines: > So, on a platform with strict alignment, in order to achieve contiguous packing of structures (required by the last) and to achieve each structure member having a valid pointer (required by the first) the implementation must add enough optional padding (allowed by the middle) to make the size of the structure aligned. It's not in the standard per se. It's a requirement for machine code to function on certain platforms. The standard basically just says that in all cases compilers have to generate machine code that works properly. It is imposed by the designers of the processor, not the C standard. > I believe the parent is referring to the int8_t, int16_t types rather than the implementation-defined int, short, long types here. This is indeed what I was talking about.
- vonmoltke 10y ago> A conforming ISO C implementation has to ensure that farray[1].first_member, and farray[2].first_member, and so on, are all allocated such that they meet the alignment requirements fro whatever_type_t. It cannot be that farray[0].first_member is accessible, but farray[1].first_member throws an alignment exception or whatever. Programmers should not have to do anything to ensure this. The alignment requirement is platform-dependent. Some platforms can perform unaligned loads, which means an object can be allocated at any byte offset in memory. There are no requirements in the C standard for alignment other than conforming to the specific hardware. > In practice, compilers add the padding even if it's not required for at least two reasons: performance (misaligned accesses, though supported, may be slow) and compatibility (having the structure look the same across multiple architectures supported by the same compiler, at most modulo byte order). Yes, and in practice this depends on the compiler and the platform, which was my point. > I'm not aware that C provides any other, currently. Though you can simulate them with libraries, of course. None of the numeric types enumerated in the standard have a fixed size associated with them in the C standard[1]. They have minimum representation ranges, but that is it. [1] I'm not counting IEEE754 floating-point types, since that is a standard imposed on the C standard itself.
- vonmoltke 10y agoI like how I'm getting downvoted, yet nobody is telling me how I'm wrong.
- yuubi 10y ago> fixed-width numeric types uint32_t and friends instead of the implementation-defined unsigned int/long. See http://pubs.opengroup.org/onlinepubs/007904975/basedefs/stdint.h.html http://pubs.opengroup.org/onlinepubs/007904975/basedefs/stdi... for many details (including things like the name for "the fastest signed integer type with at least 8 bits", which could be signed char on machines that support byte access in hardware and signed 32-bit on machines where byte addressing means loading a word, bit-bashing the new value in, and storing it back).
- blaisio 10y agoCan you give an example of a compiler and platform where this isn't true? I thought it was part of the standard, and I've never seen C code that didn't make the assumption that this is true.
- vonmoltke 10y agoIIRC, icc does not normally pad structures, since x86-64 supports unaligned loads fairly well. xlc on POWER generally tries to do what kazinator stated above because unaligned loads are expensive, if even possible, on those platforms.