Operator: alignof

  • Thread starter Frederick Gotham
  • Start date
F

Frederick Gotham

Alf P. Steinbach posted:

You could, but you forgot to; anyway, it's UB. The current language
spec has no notion of alignment, whatsoever. From the point of view of
the standard the effect could be anything, including nasal demons.


The Standard doesn't mention that dalmations have spots, but they still do.

The Standard doesn't mention that the sky is blue, but it still is.

The Standard does in fact mention alignment, but even if it didn't, it
wouldn't make a blind bit of difference, because alignment is a concrete
concept.
 
F

Frederick Gotham

Alf P. Steinbach posted:

Yes, you're right; the effect of the program is unspecified (as per
5.2.10/7), not UB.


The behaviour is very specified, and perfectly predictable.

The concept of "alignment" is very concrete. A simple way of looking at
it is that the following must be true:


!( address_of_object % alignof(Type) )


Regardless of what the Standard does and does not mention, people
understand the concept of alignment, and it makes perfect sense that the
following code is perfectly okay:

int main()
{
int array[2];

int *p = array;

p = (int*)( (char*)p + alignof(int) );

*p = 7;
}
 
F

Frederick Gotham

Robbie Hatley posted:

Why do I find myself wanting to say a rosary and pray? And I'm not
even religious. In fact, I'm an athiest. But dude! That's EVIL!!!
May the Valar protect us!!!


If the "alignof" operator gives an accurate value, then there's nothing to
fear.
 
F

Frederick Gotham

Robbie Hatley posted:
How on Earth could that work?


I don't know much about deep-down computer architecture, but I just take
people's word for it that many systems have such a setup.

Assuming a little-endian arrangement
(for sake of argument), if you had an array like this:

int Array[2] = {37, 84};

then the most-significant two bytes of MyArray[0] would overlap
in RAM with the least-significant two bytes of MyArray[1]!!!

byte byte byte byte byte byte
0x3a07 0x3a08 0x3a09 0x3a0a 0x3a0b 0x3a0c
Array[0] Array[0] Array[0] Array[0]
Array[1] Array[1] Array[1] Array[1]


Of course, the machine doesn't do that.

Or am I somehow missing what you mean by "alignment"? By "aligned
on a X-byte boundary", do you mean "the absolute numerical value of
&Array[0] must be zero modulo X"?


Something very close to that, yes.
 
R

Rolf Magnus

Frederick said:
Alf P. Steinbach posted:




The Standard doesn't mention that dalmations have spots, but they still
do.

The Standard doesn't mention that the sky is blue, but it still is.

However, that would be irelevant in this newsgroup, because here we only
talk about C++ as defined by the ISO standard.
The Standard does in fact mention alignment,

Yes, but it doesn't define any specific alingment requirements.
but even if it didn't, it wouldn't make a blind bit of difference, because
alignment is a concrete concept.

Yes, but it should not be of concern when programming in C++, except for
some very low-level code.
 
F

Frederick Gotham

Rolf Magnus posted:

Yes, but it should not be of concern when programming in C++, except
for some very low-level code.


I tend not to categorise code. Some people like to lump code into the
category of "low-level code", or "high-level code", or "encapsulated code",
or "object-orientated code".

It's all just code to me. As long as it's fully-portable, I don't mind.
 
R

Rolf Magnus

Frederick said:
Rolf Magnus posted:




I tend not to categorise code. Some people like to lump code into the
category of "low-level code", or "high-level code", or "encapsulated
code", or "object-orientated code".

It's all just code to me. As long as it's fully-portable, I don't mind.

That's actually where the separation between low-level code and high-level
code gets in. Low-level code is typically not as portable as high-level
code, because it depends on some hardware/compiler specifics like a
specific alignment.
 
F

Frederick Gotham

Rolf Magnus posted:

That's actually where the separation between low-level code and
high-level code gets in. Low-level code is typically not as portable
as high-level code, because it depends on some hardware/compiler
specifics like a specific alignment.


Yes, if written badly. Most of the time, "low-level" code, as you call it,
can be written portably -- I do it all the time.
 
H

Howard Hinnant

Fred's original code is correct: if a pointer is already correctly
aligned, then adjusting it by the alignment size will result in
another pointer which is correctly aligned.

Yes, but that's not very useful.[/QUOTE]

On Friday, April 7, 2006, the C++ committee found std::tr1::alignment_of
to be sufficiently useful to vote into the C++0X working draft. The
vote was not on alignment_of specifically, but on the TR1 type_traits
library as a whole. The vote was 28 in favor, 0 opposed, 1 abstain.

I can personally see use-cases for alignment_of, mostly in conjunction
with std::aligned_storage (in working draft), placement new, and/or the
implementation of "short string optimization" techniques.

-Howard
 
A

Alf P. Steinbach

* Howard Hinnant:
Yes, but that's not very useful.

On Friday, April 7, 2006, the C++ committee found std::tr1::alignment_of
to be sufficiently useful to vote into the C++0X working draft. The
vote was not on alignment_of specifically, but on the TR1 type_traits
library as a whole. The vote was 28 in favor, 0 opposed, 1 abstain.

I can personally see use-cases for alignment_of, mostly in conjunction
with std::aligned_storage (in working draft), placement new, and/or the
implementation of "short string optimization" techniques. [/QUOTE]

Thanks for your earlier comment (repeat, thanks for that), but this time
I'm not sure whether you're /preaching/ to the choir, or /barking/ up
the wrong tree... ;-)

Alignment information is very useful and needed for low-level memory
management, and it's a good thing that some support is added to the
standard; e.g. that might enable automatic portability in code like
Loki's small object allocator.

Accessing half of one integer and half of the next, in an array, as an
integer, is however not very useful.

Frederick's original code is not very useful.

It seemed and seems to be meaningless.
 
H

Howard Hinnant

"Alf P. Steinbach said:
Thanks for your earlier comment (repeat, thanks for that), but this time
I'm not sure whether you're /preaching/ to the choir, or /barking/ up
the wrong tree... ;-)

Probably some of both. Guilty of skimming this thread too quickly.

-Howard
 
I

Ian Collins

Frederick said:
Rolf Magnus posted:






Yes, if written badly. Most of the time, "low-level" code, as you call it,
can be written portably -- I do it all the time.
One how many different processors and compilers?
 
F

Frederick Gotham

Ian Collins posted:
One how many different processors and compilers?


One processor and one compiler.

So how could I possibly know how to do "low-level" things portably... ?
Because the Standard provides me with dozens of guarantees that are
universal to EVERY platform. Here's just a few:

(1) A byte is at least 8 bits.
(2) A char has no padding.
(3) The number system must either be 1's complement, 2's complement
or sign-magnitude.
(4) All-bits-zero is a valid zero representation for all integer
types (including those which contain padding).
(5) An unsigned long provides me with at least 32 value bits.
(6) The address of a POD is the same as the address of the first
element in the POD.
(7) All members within a union have the same address.
(8) It's okay to have a pointer to one past the last element of an
array.


I can write fully portable "low-level" code because the Standard provides
guarantees.
 
I

Ian Collins

Frederick said:
Ian Collins posted:





One processor and one compiler.
Then you aren't in a position to claim what you claim, unless you can
show us some portable driver, kernel or other truly low code you have
written.
 
F

Federick Gotham

Ian Collins posted:

Then you aren't in a position to claim what you claim, unless you can
show us some portable driver, kernel or other truly low code you have
written.


Convenient how you snipped the part that substantiated my claim.

I'll be very willing to continue this debate once you decide you've
abandoned your fairytale dream world and want to live in the real world.
 
I

Ian Collins

Federick said:
Ian Collins posted:






Convenient how you snipped the part that substantiated my claim.
A claim: "Most of the time, "low-level" code, as you call it,
can be written portably -- I do it all the time" that remains
unsubstantiated.
I'll be very willing to continue this debate once you decide you've
abandoned your fairytale dream world and want to live in the real world.
Unfortunately I've spent over 20 years working on low level code and I
can't see myself waking up any time soon.

I repeat what I said, show us some portable driver, kernel or other
truly low code you have written.
 
R

Robbie Hatley

Frederick Gotham said:
Robbie Hatley posted:


I don't know much about deep-down computer architecture, but I just take
people's word for it that many systems have such a setup.

Hmmm... That doesn't sound very confidence-inspiring. I found
that when I was doing firmware work, I had to BECOME an expert
on the deep-down architecture of the CPU I was working with,
before I could even write my first C statement. And some stuff
I couldn't do with C, so I had to resort to embedded assembly
snippets. (At one point, I even had to resort to programming
in machine language. I shudder to recall it. Jesus. No one
should have to resort to A7,B4,39,A8,8B,73,88,F3. I think
that's unconstitutional; "cruel and unusual punishment" or
something like that.)
Assuming a little-endian arrangement
(for sake of argument), if you had an array like this:

int Array[2] = {37, 84};

then the most-significant two bytes of MyArray[0] would overlap
in RAM with the least-significant two bytes of MyArray[1]!!!

byte byte byte byte byte byte
0x3a07 0x3a08 0x3a09 0x3a0a 0x3a0b 0x3a0c
Array[0] Array[0] Array[0] Array[0]
Array[1] Array[1] Array[1] Array[1]


Of course, the machine doesn't do that.

But if alignof(MyType) < sizeof(MyType), and you advance
your pointer by alignof(MyType) bytes, as you describe,
the machine will do EXACTLY that. (Computers are stupid.
They do what you say, not what you mean.)

In other words, correct "alignment" (in the way that you're
using it) does not imply correct data. Your pointer can
be "aligned" just fine, and yet point to garbage, as I
demonstrate above, and in another post in this thread. In
fact, the code you gave GUARANTEES your pointer will point
to garbage every other iteration.

This "alignment" thing might be useful for deciding on a
beginning point for an object or array, but trying to use
it to iterate through the ELEMENTS of an array is wrong
and disastrous.

This seems a thing that might be useful for writing OS kernels
and perhaps compilers, but is far too dangerous for general
usage. People would misunderstand it and misuse it.

PS: as an aside, I should mention that many compilers have
__attribute__ ((aligned)) // increase alignment
which is the opposite of
__attribute__ ((packed)) // decrease alignment
which I mentioned in an unrelated thread in this group a
couple days ago.

--
Cheers,
Robbie Hatley
Tustin, CA, USA
lonewolfintj at pacbell dot net
(put "[usenet]" in subject to bypass spam filter)
http://home.pacbell.net/earnur/
 
F

Frederick Gotham

Robbie Hatley posted:

But if alignof(MyType) < sizeof(MyType), and you advance
your pointer by alignof(MyType) bytes, as you describe,
the machine will do EXACTLY that. (Computers are stupid.
They do what you say, not what you mean.)


It's brilliant that the machine will do exactly what I want it to do. If
I wanted to advance to the next element in an array, I'd simply write:

++p;

or maybe even this if I'm feeling kinky:

p = (Type*)( (char*)p + sizeof(Type) );



But I want to advance by the alignment value, hence:


p = (Type*)( (char*)p + alignof(Type) );

In other words, correct "alignment" (in the way that you're
using it) does not imply correct data. Your pointer can
be "aligned" just fine, and yet point to garbage


Indeed. (Unless of course we're lucky enough to be dealing with a system
where an unsigned integer has no trap representations.)

This "alignment" thing might be useful for deciding on a
beginning point for an object or array, but trying to use
it to iterate through the ELEMENTS of an array is wrong
and disastrous.


Indeed, and that's not what I want to do.

This seems a thing that might be useful for writing OS kernels
and perhaps compilers, but is far too dangerous for general
usage. People would misunderstand it and misuse it.


I have faith in my competence.
 
O

Old Wolf

Similar to how it works when int is 4 bytes but need only
be aligned on a 1 byte boundary? (eg. IA32)
Assuming a little-endian arrangement
(for sake of argument), if you had an array like this:

int Array[2] = {37, 84};

then the most-significant two bytes of MyArray[0] would overlap
in RAM with the least-significant two bytes of MyArray[1]!!!

byte byte byte byte byte byte
0x3a07 0x3a08 0x3a09 0x3a0a 0x3a0b 0x3a0c
Array[0] Array[0] Array[0] Array[0]
Array[1] Array[1] Array[1] Array[1]

Array[1] starts at 0x3a0b. Array members are contiguous
and non-overlapping in memory, regardless of alignment
requirements.
But if alignof(MyType) < sizeof(MyType), and you advance
your pointer by alignof(MyType) bytes, as you describe,
the machine will do EXACTLY that.

You can access four bytes starting at 0x3a09 as an integer,
but it isn't called Array[1], and it might be a trap representation
if Array[0] and Array[1] have been assigned values.
In fact, the code you gave GUARANTEES your pointer will point
to garbage every other iteration.
This "alignment" thing might be useful for deciding on a
beginning point for an object or array, but trying to use
it to iterate through the ELEMENTS of an array is wrong
and disastrous.

It can't be used for iterating through the elements of an array.
Fred's original code didn't include any iteration.
This seems a thing that might be useful for writing OS kernels
and perhaps compilers, but is far too dangerous for general
usage. People would misunderstand it and misuse it.

You could say that about many features of the C language :)

I've had need of it once: when working on an embedded
platform where I needed to establish a data structure in
some allocated memory, but the block of memory was not
guaranteed to have any particular alignment.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,780
Messages
2,569,611
Members
45,266
Latest member
DavidaAlla

Latest Threads

Top