tags:

views:

86

answers:

3
+1  A: 

Q1: Alignment isn't related to size.

Q2: Theoretically yes, but you will hardly find an architecture that has a type with such huge alignment. SSE requires 16 bytes alignment (the biggest I have seen).

Let_Me_Be
@Let_Me_Be: The reason I supposed the alignment **is** related to size is that if I take an array of X's and all of them should obey the alignment requirements then the addresses a, a+sizeof(X), a+2*sizeof(X) ... etc. should all conform these requirements. Which led me to define the statement. Am I wrong?
Armen Tsirunyan
@Armen: You got it upside down. The object's size has to be a multiple of its alignment. A `char` usually has alignment 1, and an `int` usually has to be aligned on a 4-byte boundary. A `struct` containing both is given the alignment of it's most strictly-aligned member (so if it contains a `char` and an `int`, then the struct as a whole requires the same alignment as an `int` does). The object must then also have a size that is some multiple of an int. The same is true for your huge char array. It contains nothing but chars, and each char can be placed at any byte (any address divisible by 1)
jalf
so the array as a whole has the same alignment requirement (and also has to be a multiple of 1, which isn't difficult to achieve. ;))
jalf
@jalf: Thanks, that cleared some things up. Just tell me this. p = new char[100]; new(p+1)someComplexStruct; Is this safe or not?
Armen Tsirunyan
@Armen: it is not. The char array is (because it is allocated with `new` aligned using the strictest possible alignment (as @James described in his answer), so `new(p) someComplexStruct` would be safe. But `p+1` is, by definition, going to be one byte (well, one char, for you purists) past the beginning of `p`. And so, if `p` is well aligned, `p+1` is *not*. (Unless `someComplexStruct` has the same alignment requirement as a `char`)
jalf
@jalf: Even purists will agree that one char is always one byte :) But they would argue how many bits that is :)) Now, I understand what you said. Now what about new(p+sizeof(someComplexStruct)) someComplexSttruct? This is bound to be legal, but I can't understand why
Armen Tsirunyan
@Armen: No, they won't. ;) A `char` is not defined to be any specific number of bytes. It is just the smallest unit of addressable memory used in C++. But a `char` can be 2 or 4 bytes, for example.
jalf
Yes, that looks legal to me. What don't you understand about it? If `p` is aligned so that some type T can be legally constructed there, then `p+sizeof(T)` will also be aligned so a `T` can be constructed there, because the size of a type is required to be a multiple of its alignment
jalf
@Jalf: Thank you very much. I got it finally! If you would consider incorporating your comments into an answer that would be one wonderful answer useful to the readers... :) Naturally it would be instantly accepted
Armen Tsirunyan
@jalf The standard actually refers to `char` as `byte`, but doesn't specify the number of bits per byte. I tend to call it C-byte.
Let_Me_Be
@Let_Me_Be: where does it refer to a `char` as `byte`? As far as I can see, it defines a `byte` as the smallest addressable unit of memory, but it says nothing about the size in bytes of *any* object. `char`'s size is given as 1, but not 1 *byte*. Just 1. So as far as I can see, a perfectly conforming implementation could use, say, 12-bit bytes and 24-bit chars. As long as ever C++ object is a multiple of `char`'s size, it's legal. Or where does it say otherwise?
jalf
@jalf: The standard explicitly specifies that sizeof(char) == 1 and that sizeof is the number of bytes occupied by the object... so char occupies one byte, no doubt there, but the standard also says "a byte is a contiguous sequence of 1 or more bits"
Armen Tsirunyan
@jalf C99 - terms and definitions: `byte` addressable unit of data storage large enough to hold any member of the basic characterset of the execution environment `NOTE 1` It is possible to express the address of each individual byte of an object uniquely. `NOTE 2` A byte is composed of a contiguous sequence of bits, the number of which is implementation defined. The least significant bit is called the low-order bit; the most significant bit is called the high-order bit.
Let_Me_Be
@jalf: C++ 2003 Par 5.3.3 Clause 1 ***The sizeof operator yields the number of bytes in the object representation of its operand***. The operandis either an expression, which is not evaluated, or a parenthesized type-id. The sizeof operator shall notbe applied to an expression that has function or incomplete type, or to an enumeration type before all itsenumerators have been declared, or to the parenthesized name of such types, or to an lvalue that designatesa bit-field. ***sizeof(char), sizeof(signed char) and sizeof(unsigned char) are 1;***
Armen Tsirunyan
@jalf C++03 - C++ memory model: The fundamental storage unit in the C++ memory model is the byte. A byte is at least large enough to contain any member of the basic execution character set and is composed of a contiguous sequence of bits, the number of which is implementation-defined. The least significant bit is called the low-order bit; the most significant bit is called the high-order bit. The memory available to a C++ program consists of one or moresequences of contiguous bytes. Every byte has a unique address.
Let_Me_Be
@Armen, @Let: thanks, both of you. You learn something new every day :)
jalf
+4  A: 

When you dynamically allocate memory using operator new, you have the guarantee that:

The pointer returned shall be suitably aligned so that it can be converted to a pointer of any complete object type and then used to access the object or array in the storage allocated (until the storage is explicitly deallocated by a call to a corresponding deallocation function) (C++03 3.7.3.1/2).

vector does not create an array of char; it uses an allocator. The default allocator uses ::operator new to allocate memory.

James McNellis
+2  A: 

An alignment requirement for an object of type X where sizeof(X) == n is at least the requirement that address of X be divisible by n or something like that

No. The alignment requirement of a type is always a factor of its size, but need not be equal to its size. It is usually equal to the greatest of the alignment requirements of all the members of a class.

An array of 5M char, on its own account, need only have an alignment requirement of 1, the same as the alignment requirement of a single char.

So, the text you quote about the alignment of memory allocated via global operator new, (and malloc has a similar although IIRC not identical requirement) in effect means that a large allocation must obey the most stringent alignment requirement of any type in the system. Further to that, implementations often exclude large SIMD types from this, and require that memory for SIMD be specially allocated. This is slightly dubious, but I think they justify it on the basis that non-standard, extension types can impose arbitrary special requirements.

So in practice the number which you think is 5000000 is often 4 :-)

Steve Jessop