Libecb: notes about alignas and alignof

Zsb√°n Ambrus ambrus at math.bme.hu
Sat Aug 8 18:05:10 CEST 2015


I'd really like a portable way to use alignof and alignas.  This seems
impossible, especially on old compilers, but I still think libecb
might still try to help in some cases.  I don't know the final
solution of what could be done, so here I'm trying to collect
information about what compilers support what features, and how you
can test them without a configure system.  I'll take alignof and
alignas separately.  These are mostly symmetric, but have differences.

== alignof ==
The C++11 alignof keyword queries the required alignment of a type.

1. The alignof keyword is available in C++11, C++ in starting from gcc
4.8, C++ in clang if __has_feature(cxx_alignas), but not yet in any
version of the MS compiler.
2. The _Alignof keyword, and the macro alignof in <stdalign.h>, is
available in C11, and I don't know the compiler versions.
3. The GCC __alignof__ keyword is available starting from ancient
times (before gcc 3).
4. The MS compiler has an __alignof keyword.
5. The std::alignment_of template in <type_traits> would be a suitable
replacement to alignof, but it's probably only available in C++11
compilers that have alignof anyway.
6. Boost has an implementation of the alignment_of in the TypeTraits
library for some compilers, unknown header and namespace, which might
give some hints if only you could untangle the source code.
7. The boost config module has some macros like BOOST_NO_CXX11_ALIGNAS
that try to tell whether compilers have C++11 alignas, but it's hard
to read the boost source code to find out how this works, and it's
sometimes not precise, so it's useful only as a starting point.

== alignas ==
The alignas specifier is more complicated because it can syntactically
appear in multiple places in the code (qualifying a struct or an
object declaration), and only some of these could be possible on
certain compilers, and also because it can take both a type or a value
as its parameter.  Let me talk about these separately now.

1. The alignas keyword is available in C++11, C++ in starting from gcc
4.8, unknown versions of clang, but not yet in any version of the MS
compiler.
2. The _Alignas keyword, and the macro alignas in <stdalign.h>, is
available in C11, and I don't know the compiler versions.
3. There's a gcc-specific attribute __attribute__((aligned()))
starting from ancient times (before gcc 3), and can be applied to both
structure and variable definitions.  This takes only an alignment
number parameter, not a type.
4. There's an MS complier attribute __declspec(align()).  I think this
doesn't quite support the full semantics of alignof, but can still
help in some cases.  The MSDN documentation at
"https://msdn.microsoft.com/en-us/library/83ythb65.aspx" promises a
lot but is a bit suspicious and haven't been updated for a while.  In
any case, the MS compiler seems to have some strange ideas about
alignment, in particular, it sometimes doesn't align objects on the
stack, which could be why they don't want to add the alignas keyword.
Still, this attribute may help for at least global variables.
5. The std::aligned_storage template class lets you create overaligned
types in some special cases and with ugly syntax.  However, it is
probably available only in C++11 compilers that have alignas anyway,
so it won't help much.
6. Boost has an implementation of aligned_storage somewhere in the
TypeTraits module, which could give some hints.
8. You can sometimes use a union with a highly aligned type to create
aligned storage, but this only helps if you have a type that's highly
aligned in first place, so 64-byte alignment this way is impossible
except in the latest systems.

The syntax of where you can place these in a declaration is picky, and
differ for these.  For a struct definition, put alignas(32) or
__attribute__((aligned(32))) or __declspec(align(32)) between the
struct keyword and the name of the newly defined structure type.  For
a variable (member) definition, put alignas(32) or
__attribute((aligned(32))) or __declspec(align(32)) at the very
beginning of the declaration.  Placing them like these is at least
accepted without a warning on some compilers, but it's hard to be sure
it actually set alignment.

== other stuff ==
Sometimes I'd like an aligned_alloc function (as in C11).  Most C
libraries, even the oldest ones, seem to have something like this, but
with lots of differences in the interface.  Boost has an
implementation which seems to work, but I think it doesn't always do
the optimal thing.  This, however, probably does not belong to libecb.

Slightly related is reading and writing unaligned integers in the
memory (and possibly floats too).  Boost now has a library that I can
use for this (called Endian), which supports unaligned integers of all
sizes and endiannesses, with a C++ interface.  This has at least some
platform-specific optimizations for endianness swaps.  I don't know
whether it can handle unaligned accesses efficiently, and that might
even be impossible on x86 systems, where some cpu instructions allow
unaligned access, some don't, some depend on some modes or states or
cpu types, and compilers don't seem to have an interface to do
unaligned access, even though I think they should.  I've used this
library to read a misaligned int64_t recently, but that didn't require
any sort of performance.  Anyway, if you can figure out how to handle
this properly, some functions for this could still be useful for
libecb.

-- Ambrus



More information about the libev mailing list