Why alignment is power of 2?
Asked Answered
S

2

14

There is a quote from cppreference:

Every object type has the property called alignment requirement, which is an integer value (of type std::size_t, always a power of 2) representing the number of bytes between successive addresses at which objects of this type can be allocated.

I understand, this reference is non-normative. But there is no something about value of alignof(T) in the standard, rather than it is no more than alignof(std::max_align_t).

It is not obviously, that alignment is power of 2. Why does alignment not be a 3?

Sculptress answered 16/7, 2014 at 18:39 Comment(2)
en.wikipedia.org/wiki/Data_structure_alignment addresses this to a degree. In particular, when computing padding to maintain word alignment: "Since the alignment is by definition a power of two, the modulo operation can be reduced to a bitwise boolean AND operation."Rabjohn
Info about Memory Aligment, the reason for why not allow 3 probably is because it would cause more damage than good (bad alignment for mistakes in the code, too bad complexity implementing functionality that if used, will be in extremely if any strange cases).Anceline
P
11

The standard has the final word for the language, so here a quote of that section. I bolded the power-of-2 requirement:

3.11 Alignment [basic.align]

1 Object types have alignment requirements (3.9.1, 3.9.2) which place restrictions on the addresses at which an object of that type may be allocated. An alignment is an implementation-defined integer value representing the number of bytes between successive addresses at which a given object can be allocated. An object type imposes an alignment requirement on every object of that type; stricter alignment can be requested using the alignment specifier (7.6.2).
2 A fundamental alignment is represented by an alignment less than or equal to the greatest alignment supported by the implementation in all contexts, which is equal to alignof(std::max_align_t) (18.2). The alignment required for a type might be different when it is used as the type of a complete object and when it is used as the type of a subobject. [ Example:

struct B { long double d; };
struct D : virtual B { char c; }

When D is the type of a complete object, it will have a subobject of type B, so it must be aligned appropriately for a long double. If D appears as a subobject of another object that also has B as a virtual base class, the B subobject might be part of a different subobject, reducing the alignment requirements on the D subobject. —end example ] The result of the alignof operator reflects the alignment requirement of the type in the complete- object case.
3 An extended alignment is represented by an alignment greater than alignof(std::max_align_t). It is implementation-defined whether any extended alignments are supported and the contexts in which they are supported (7.6.2). A type having an extended alignment requirement is an over-aligned type. [ Note: every over-aligned type is or contains a class type to which extended alignment applies (possibly through a non-static data member). —end note ]
4 Alignments are represented as values of the type std::size_t. Valid alignments include only those values returned by an alignof expression for the fundamental types plus an additional implementation-defined set of values, which may be empty. Every alignment value shall be a non-negative integral power of two.
5 Alignments have an order from weaker to stronger or stricter alignments. Stricter alignments have larger alignment values. An address that satisfies an alignment requirement also satisfies any weaker valid alignment requirement.

Why did all implementations conform to that requirement (That's part of the reason it could be included at all)?

Well, because it is natural to multiply / divide / mask powers of 2 in binary, and all systems were (excluding some really ancient ones), are, and for the foreseeable future will stay fundamentally binary.
Being natural means it is much more efficient than any other multiplications / divisions / modulo arithmetic, sometimes by orders of magnitude.

As @MooingDuck points out, this fundamental binary nature of computing platforms has already pervaded the language and its standard to such an extent, trying to build a non-binary conforming implementation is about on-par with untying the gordian knot without just cutting it. There are really few computer languages where that's not true.

Also, see a table of word sizes on wikipedia for corroboration.

Porter answered 16/7, 2014 at 19:9 Comment(1)
The C++spec refers to 2 enough that it its pointless to make a conforming ternary implementation. The rules for how individual bytes rollover inside of a multibyte fundamental type are the sticking points.Joyejoyful
H
4

That's how computers are built.

A computer has a natural 'word' size that is handled more easily than other sizes. On 64-bit CPUs, the size is 8-bytes. Operating on 8-bytes is most efficient. The hardware is built in a way that fetching memory that is aligned to this word size is also more efficient. So alignment is usually based on the CPU's word size.

Word sizes are powers of two because, again, that's how computers are built. Everything comes down to bits - so does the number of bits in a word. It's easier to design the hardware where the number of bits in a word is itself a power of two.

Histopathology answered 16/7, 2014 at 18:43 Comment(13)
It has to do with the way address and data buses are actually wired to caches and memory devices. It's probably not worth the effort it would take to understand this unless you really need to know for some reason. (For example, if you're trusted to design the schematic for a 16-bit microcontroller and need to hook its buses up to two 8-bit EPROMs and don't want to wind up delivering a dozen boards professionally made and stuffed but with their address and data buses wired completely wrong. But I'm not bitter.)Roseboro
Where's my PDP with 36 bits per word?Porter
This question is about the low-level details. Please do not use byte and similar words which have a specific definition in C and C++ with a differing meaning without explicitly calling attention to your explicitly given changed definition.Porter
It is a bit unclear. I'll try to explain what exactly unclear for me. Ok, assume that word size is power of two. I don't understand how does that word-size prevents to have an object with alignment equal 3?Sculptress
@Sculptress Right, you don't. And you'd need to understand how address and data buses are actually wired to understand why that prevents it. The short version -- the hardware simply could not deliver the data to the right place because the wires don't run that way. (It could, of course, read it in a different way and then copy it where it needed it. But that would cause horrible performance problems.)Roseboro
@DavidSchwartz That is, it is just hardware rule and independent from programming language design.Sculptress
@Sculptress I wouldn't quite say it's independent, just that it's a hardware rule that programming language design has to take into account.Roseboro
@St.Antario, it is indeed a hardware 'rule'. The hardware is designed in such a way that accessing memory on a whole word boundry is faster. And it's easier to design hardware in such a way that the word size int bits is a power of two.Histopathology
@Deduplicator, byte and word are not C/C++ specific terms... A byte is 8 bits on any recent hardware, and a word is a word.Histopathology
@zmbq: This question is in C++ and the quotes are C++ specific. There are other systems which define those terms another way, yes. But if you, in a C / C++ context about the nitty-gritty make the assumption that all the world is a VAX respective use non-C / non-C++ terminology, please be explicit.Porter
@St.Antario: Only in so far as the specific rules of the language are concerned, but not their underlying reasons. Still, at leat alignment is the same term in C / C++ and outside. The same cannot be said for byte for example.Porter
@Deduplicator: Does a 36-bit PDP use subdivide 36-bit words into three groups of 12, or four groups of 9? If it did the former, then the natural alignment would be to multiples of 3, but I think most machines with 36-bit words subdivide into four groups of 9, meaning that the natural alignment would be to multiples of 4.Geologize
@Sculptress - The reason you can't have an alignment equal to 3 is because alignment specifies how many of the consecutive lowest bits of the address of the thing being aligned will be zero. There is no way to express "3" using a consecutive series of blank low-order bits in an address.Alp

© 2022 - 2024 — McMap. All rights reserved.