By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
446,194 Members | 854 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 446,194 IT Pros & Developers. It's quick & easy.

Operator: alignof

P: n/a
It is possible and permissible on a given system, that the alignment
requirements of a type are less than the size of that type. For instance,
here's a hypothetical set-up:

int is 4 bytes, but need only be aligned on a 2 byte boundary.

If we had some sort of "alignof" operator, then we would be able to do
the following:

int main()
{
int array[2];

int *p = array;
/* The following function is defined elsewhere. I use it
here to make this snippet as simple as possible. */

AdvancePointerByBytes( p, alignof(int) );

*p = 5;
}
Over on comp.lang.c, Hallvard B Furuseth devised such an operator, and a
lot of people use it.

I've adapted it to C++, and I've written a sample program consisting of
two headers and one source file. Any thoughts on it?
/* BEGINNING OF advance_ptr.hpp */

#ifndef INCLUDE_ADVANCE_PTR_HPP
#define INCLUDE_ADVANCE_PTR_HPP

#include <cstddef>

template<class T>
inline void AdvancePtr( T * &p, std::size_t const bytes )
{
p = reinterpret_cast< T* >(
const_cast<unsigned char *>(
reinterpret_cast<const unsigned char *>(p) + bytes
)
);
}

template<class T>
inline void RetreatPtr( T * &p, std::size_t const bytes )
{
p = reinterpret_cast< T* >(
const_cast<unsigned char *>(
reinterpret_cast<const unsigned char *>(p) - bytes
)
);
}

#endif

/* END OF advance_ptr.hpp */
/* BEGINNING OF alignof.hpp */

#ifndef INCLUDE_ALIGNOF_HPP
#define INCLUDE_ALIGNOF_HPP

#include <cstddef>

template<class T>
struct StructForAlign {

unsigned char first_byte;
T obj;

};

#define alignof(type) ( offsetof( StructForAlign< type >, obj ) )

#endif

/* END OF alignof.hpp */
/* BEGINNING OF main.cpp */
#include <iostream>

#include "advance_ptr.hpp"

#include "alignof.hpp"

int main()
{
long double array[2];

long double *p = array;

AdvancePtr( p, alignof(long double) );

*p = 23235.2352;

std::cout << *p << '\n';
}
/* END OF main.cpp */
--

Frederick Gotham
Jul 1 '06 #1
Share this Question
Share on Google+
39 Replies


P: n/a
Frederick Gotham wrote:
It is possible and permissible on a given system, that the alignment
requirements of a type are less than the size of that type. For instance,
here's a hypothetical set-up:


I don't understand what you are trying to do. Presuming you
have such an operator what would it be used for?
Jul 1 '06 #2

P: n/a
In article <kS*******************@news.indigo.ie>,
Frederick Gotham <fg*******@SPAM.com> wrote:
If we had some sort of "alignof" operator, then ...


This is currently in the C++0X working draft:

http://www.open-std.org/jtc1/sc22/wg...2006/n2009.pdf

Search for alignment_of.

In the meantime, workarounds such as yours, boost::alignment_of, and
std::tr1::alignment_of are available.

-Howard
Jul 1 '06 #3

P: n/a
* Frederick Gotham:
It is possible and permissible on a given system, that the alignment
requirements of a type are less than the size of that type. For instance,
here's a hypothetical set-up:

int is 4 bytes, but need only be aligned on a 2 byte boundary.
Yes, of course: for most types and platforms alignment is less than the
size of an object of the type.

C++ as a language does not address alignment.

Alignment requirements arise from the hardware (system bus, memory
interface) and from the OS (some can fix alignment faults, at cost, and
in Windows this can be configured).

If we had some sort of "alignof" operator, then we would be able to do
the following:

int main()
{
int array[2];

int *p = array;
/* The following function is defined elsewhere. I use it
here to make this snippet as simple as possible. */

AdvancePointerByBytes( p, alignof(int) );

*p = 5;
}
What are you trying to do? 'array' is already suitably aligned for
'int'. Also, advancing a pointer by the alignment value for a type
doesn't make the pointer well-aligned for that type. Instead you need
to treat the address as an integer and advance it to the next multiple
of the alignment value, if not already at such multiple. Like

typedef unsigned long ulong; // Assuming ulong is enough.
char array[1000];
ulong const a = (ulong)(&a[0]) + alignment(int) - 1; // ...
int* p = (int*)(a - a%alignment(int));

which for 2^x alignment is usually done by bit-operations.

Over on comp.lang.c, Hallvard B Furuseth devised such an operator, and a
lot of people use it.

I've adapted it to C++, and I've written a sample program consisting of
two headers and one source file. Any thoughts on it?
/* BEGINNING OF advance_ptr.hpp */

#ifndef INCLUDE_ADVANCE_PTR_HPP
#define INCLUDE_ADVANCE_PTR_HPP

#include <cstddef>

template<class T>
inline void AdvancePtr( T * &p, std::size_t const bytes )
{
p = reinterpret_cast< T* >(
const_cast<unsigned char *>(
reinterpret_cast<const unsigned char *>(p) + bytes
)
);
}


This is IMO mixing incompatible levels of abstraction. Alignment is
part of low-level functionality where you don't really care about the
type T that the pointer will finally end up pointing to. It's IMO
Ungood and almost Evil(TM) to offer client code "easy" functionality to
mix such low-level things with higher level code.

Although I haven't used it, on general grounds I recommend you take a
look at the Boost utility referenced else-thread.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Jul 1 '06 #4

P: n/a
Alf P. Steinbach posted:
Also, advancing a pointer by the alignment value for a type
doesn't make the pointer well-aligned for that type.

If we advance it in terms of bytes, and if the original pointer value is
the address of a valid object, then I believe that it does.

Instead you need to treat the address as an integer and advance it to
the next multiple of the alignment value, if not already at such
multiple. Like

typedef unsigned long ulong; // Assuming ulong is enough.
char array[1000];
ulong const a = (ulong)(&a[0]) + alignment(int) - 1; // ...
int* p = (int*)(a - a%alignment(int));

which for 2^x alignment is usually done by bit-operations.

I don't see why you think that is necessary.

I'll explain my stance by providing two code snipppets which do exactly
the same thing:

Code Snippet (1)
----------------

int main()
{
double d[2];

double *p = d;

++p;

/* Now points to next element */
}
Code Snippet (2)
----------------

int main()
{
double d[2];

double *p = d;

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

/* Now points to next element */
}
I want the pointer arithmetic to work in terms of bytes, and thus I use
char* -- there's absolutely nothing wrong with that.

Only when we go converting pointer values to integer types do things
start to become non-portable -- and fortunately, there's no need to do
that.

In my original example: Instead of advancing the pointer by the size of
the object, I advance it by the alignment requirement, and thus it should
be perfectly okay to treat that address as the address of an object of
that type.
--

Frederick Gotham
Jul 1 '06 #5

P: n/a
* Frederick Gotham:
Alf P. Steinbach posted:
Also, advancing a pointer by the alignment value for a type
doesn't make the pointer well-aligned for that type.


If we advance it in terms of bytes, and if the original pointer value is
the address of a valid object, then I believe that it does.


Nope. Say as integer the pointer value is 1234567. The alignment is 4.
Adding 4 yields 1234571, which is just as unaligned: you want 1234570.

Advancing by the alignment only yields a well-aligned pointer if the
original pointer is well-aligned.

In which case alignment is irrelevant.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Jul 1 '06 #6

P: n/a
* Alf P. Steinbach:
* Frederick Gotham:
Alf P. Steinbach posted:
Also, advancing a pointer by the alignment value for a type doesn't
make the pointer well-aligned for that type.
If we advance it in terms of bytes, and if the original pointer value
is the address of a valid object, then I believe that it does.


Nope. Say as integer the pointer value is 1234567. The alignment is 4.
Adding 4 yields 1234571, which is just as unaligned: you want 1234570.


Urgh. Sorry about that 1234570. I leave it as an exercise for the
reader to deduce the /correct/ value you'd want.

Advancing by the alignment only yields a well-aligned pointer if the
original pointer is well-aligned.

In which case alignment is irrelevant.


--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Jul 1 '06 #7

P: n/a
Alf P. Steinbach posted:
* Frederick Gotham:
Alf P. Steinbach posted:
Also, advancing a pointer by the alignment value for a type
doesn't make the pointer well-aligned for that type.


If we advance it in terms of bytes, and if the original pointer value
is the address of a valid object, then I believe that it does.


Nope. Say as integer the pointer value is 1234567. The alignment is
4.
Adding 4 yields 1234571, which is just as unaligned: you want
1234570.

Please use a mono-width font to view this.

First of all, let's assume that:

sizeof(int) == 4
alignof(int) == 2

Here's a diagram of memory. Each memory block constitutes one byte. Four-
byte boundaries are drawn as a column of [4]. Two-byte boundaries are
drawn as a column of [2]. (Of course, a four-byte boundary also
constitutes a two-byte boundary).

Above each arrow is written the address of the byte at that memory
location.
4 5 6 7 8 9 10 11
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
V V V V V V V V
[4]---------[2]---------[4]---------[2]---------[4]
[4]| | |[2]| | |[4]| | |[2]| | |[4]
[4]| | |[2]| | |[4]| | |[2]| | |[4]
[4]| | |[2]| | |[4]| | |[2]| | |[4]
[4]| | |[2]| | |[4]| | |[2]| | |[4]
[4]| | |[2]| | |[4]| | |[2]| | |[4]
[4]---------[2]---------[4]---------[2]---------[4]
If we were to create an array of two ints, then they could be positioned
as follows:

First byte First byte
of first int of second int

4 8
| |
| |
| |
V V
[4]---------[2]---------[4]---------[2]---------[4]
[4]| | |[2]| | |[4]| | |[2]| | |[4]
[4]| | |[2]| | |[4]| | |[2]| | |[4]
[4]| | |[2]| | |[4]| | |[2]| | |[4]
[4]| | |[2]| | |[4]| | |[2]| | |[4]
[4]| | |[2]| | |[4]| | |[2]| | |[4]
[4]---------[2]---------[4]---------[2]---------[4]
Naturally, if we get a pointer to the first int, and increment it, then
the pointer advances by sizeof(int) bytes, i.e. 4 bytes, and the pointer
then points to the second int.

What I'm proposing however is this:
Get a pointer to the first int, and advance it by alignof(int) bytes,
i.e. 2 bytes. The result can be seen as follows:
First byte Pointer First byte
of first int points of second int
to

4 6 8
| | |
| | |
| | |
V V V
[4]---------[2]---------[4]---------[2]---------[4]
[4]| | |[2]| | |[4]| | |[2]| | |[4]
[4]| | |[2]| | |[4]| | |[2]| | |[4]
[4]| | |[2]| | |[4]| | |[2]| | |[4]
[4]| | |[2]| | |[4]| | |[2]| | |[4]
[4]| | |[2]| | |[4]| | |[2]| | |[4]
[4]---------[2]---------[4]---------[2]---------[4]
From the diagram, we can see that the pointer points to an address which
is aligned on a two-byte boundary. This is sufficient alignment for an
int on this system. Therefore the following code is A-OK:

int main()
{
unsigned array[2];

unsigned *p = array;

p = (unsigned*)( (char*)p + alignof(int) );
*p = 5;
}

--

Frederick Gotham
Jul 1 '06 #8

P: n/a
* Frederick Gotham:
the following code is A-OK:

int main()
{
unsigned array[2];

unsigned *p = array;

p = (unsigned*)( (char*)p + alignof(int) );
*p = 5;
}


Except for formally being UB, yes, it's OK, but I couldn't believe that
was what you meant to do. Why on earth do you want to do this?

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Jul 1 '06 #9

P: n/a
Alf P. Steinbach posted:
* Frederick Gotham:
the following code is A-OK:

int main()
{
unsigned array[2];

unsigned *p = array;

p = (unsigned*)( (char*)p + alignof(int) );
*p = 5;
}
Except for formally being UB,

I contest that assertion. If the value attained by "alignof" is
legitimate, then it is perfectly legitimate to do what I've been doing.
It is no more outlandish than:

#include <cstdlib>

int main()
{
double *p = static_cast<double*>(
std::malloc( 64 * sizeof(double) )
);

p += 47;

*p = 2452.2352;
}

yes, it's OK, but I couldn't believe that
was what you meant to do. Why on earth do you want to do this?

Just for fun! Although perhaps in the future someone will find an
application for it.
--

Frederick Gotham
Jul 1 '06 #10

P: n/a
* Frederick Gotham:
Alf P. Steinbach posted:
* Frederick Gotham:
the following code is A-OK:

int main()
{
unsigned array[2];

unsigned *p = array;

p = (unsigned*)( (char*)p + alignof(int) );
*p = 5;
}

Except for formally being UB,


I contest that assertion.


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.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Jul 1 '06 #11

P: n/a
Frederick Gotham wrote:
From the diagram, we can see that the pointer points to an address which
is aligned on a two-byte boundary. This is sufficient alignment for an
int on this system. Therefore the following code is A-OK:

I understand you could do that if you knew the alignment, I'm still
looking for an example of WHAT GOOD IT WILL DO YOU to be able to
do that? What purpose does this exercise serve?
Jul 1 '06 #12

P: n/a
Ron Natalie posted:

I understand you could do that if you knew the alignment, I'm still
looking for an example of WHAT GOOD IT WILL DO YOU to be able to
do that? What purpose does this exercise serve?

95% of my endevours here serve no purpose -- I program out of hobby, not
out of necessity.
--

Frederick Gotham
Jul 1 '06 #13

P: n/a
In article <4g*************@individual.net>,
"Alf P. Steinbach" <al***@start.nowrote:
* Frederick Gotham:
Alf P. Steinbach posted:
* Frederick Gotham:
the following code is A-OK:

int main()
{
unsigned array[2];

unsigned *p = array;

p = (unsigned*)( (char*)p + alignof(int) );
*p = 5;
}
Except for formally being UB,
I contest that assertion.

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 current language does have a notion of alignment. Specific
alignments are implementation defined (not undefined). E.g. 3.9p5:
Object types have alignment requirements (3.9.1, 3.9.2). The alignment
of a complete object type is an implementation-defined integer value
representing a number of bytes; an object is allocated at an address that
meets the alignment requirements of its object type.
-Howard
Jul 1 '06 #14

P: n/a
Alf P. Steinbach wrote:
* Frederick Gotham:
> int main()
{
int array[2];
int *p = array;
AdvancePointerByBytes( p, alignof(int) );

*p = 5;
}

What are you trying to do? 'array' is already suitably aligned for
'int'. Also, advancing a pointer by the alignment value for a type
doesn't make the pointer well-aligned for that type. Instead you need
to treat the address as an integer
Addresses need not be treatable as integers -- the memory
model may not be flat, and there may be no defined conversion
from pointer to integer, or the conversion may not be homomorphic.
and advance it to the next multiple of the alignment value, if not
already at such multiple.
There could be a system where objects have to be aligned
to an address of the type 4m+1 (supposing there is a flat
memory model).

typedef unsigned long ulong; // Assuming ulong is enough.
char array[1000];
ulong const a = (ulong)(&a[0]) + alignment(int) - 1; // ...
int* p = (int*)(a - a%alignment(int));
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. In your later post
you seem to be talking as if the original pointer:
> int array[2];
int *p = array;
were somehow not correctly aligned for int.

Jul 2 '06 #15

P: n/a
* Howard Hinnant:
In article <4g*************@individual.net>,
"Alf P. Steinbach" <al***@start.nowrote:
>* Frederick Gotham:
>>Alf P. Steinbach posted:

* Frederick Gotham:
the following code is A-OK:
>
int main()
{
unsigned array[2];
>
unsigned *p = array;
>
p = (unsigned*)( (char*)p + alignof(int) );
>
>
*p = 5;
}
Except for formally being UB,
I contest that assertion.
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 current language does have a notion of alignment. Specific
alignments are implementation defined (not undefined). E.g. 3.9p5:
>Object types have alignment requirements (3.9.1, 3.9.2). The alignment
of a complete object type is an implementation-defined integer value
representing a number of bytes; an object is allocated at an address that
meets the alignment requirements of its object type.
Yes, you're right; the effect of the program is unspecified (as per
5.2.10/7), not UB.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Jul 2 '06 #16

P: n/a
* Old Wolf:
Alf P. Steinbach wrote:
>* Frederick Gotham:
>> int main()
{
int array[2];
int *p = array;
AdvancePointerByBytes( p, alignof(int) );

*p = 5;
}
What are you trying to do? 'array' is already suitably aligned for
'int'. Also, advancing a pointer by the alignment value for a type
doesn't make the pointer well-aligned for that type. Instead you need
to treat the address as an integer

Addresses need not be treatable as integers -- the memory
model may not be flat, and there may be no defined conversion
from pointer to integer, or the conversion may not be homomorphic.
Yes.

>and advance it to the next multiple of the alignment value, if not
already at such multiple.

There could be a system where objects have to be aligned
to an address of the type 4m+1 (supposing there is a flat
memory model).
In principle, yes, but the same technique for obtaining an aligned
pointer applies.

> typedef unsigned long ulong; // Assuming ulong is enough.
char array[1000];
ulong const a = (ulong)(&a[0]) + alignment(int) - 1; // ...
int* p = (int*)(a - a%alignment(int));

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.

In your later post
you seem to be talking as if the original pointer:
>
>> int array[2];
int *p = array;

were somehow not correctly aligned for int.
No, I presented an example that could be useful, with 'array' of 'char'.
--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Jul 2 '06 #17

P: n/a
"Frederick Gotham" <fg*******@SPAM.comwrote:
It is possible and permissible on a given system, that the alignment
requirements of a type are less than the size of that type. For instance,
here's a hypothetical set-up:

int is 4 bytes, but need only be aligned on a 2 byte boundary.
How on Earth could that work? 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]

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"? But why should anyone care? That's
all "behind the scenes". Unless you're writing the lowest-level code
for memory management in some OS kernel, I don't see the point.

--
Curious,
Robbie Hatley
Tustin, CA, USA
lonewolfintj at pacbell dot net
(put "[usenet]" in subject to bypass spam filter)
http://home.pacbell.net/earnur/
Jul 2 '06 #18

P: n/a
"Frederick Gotham" <fg*******@SPAM.comboggled my mind with
the following words of wit:
First of all, let's assume that:

sizeof(int) == 4
alignof(int) == 2

Get a pointer to the first int, and advance it by alignof(int) bytes,
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!!!

You could do...

#include <iostream>
int main(void)
{
int EvilArray[666];
EvilArray[0] = 37;
EvilArray[1] = 82;
int* Dagger = &EvilArray[0];
Dagger = (int*)((char*)Dagger + 2);
std::cout << (*Dagger) << std::endl;
return 0;
}

Prints 5373952. Ewww. ::shudders:: It's the work of Morgoth!!!

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

P: n/a
Frederick Gotham wrote:
Ron Natalie posted:

>I understand you could do that if you knew the alignment, I'm still
looking for an example of WHAT GOOD IT WILL DO YOU to be able to
do that? What purpose does this exercise serve?


95% of my endevours here serve no purpose -- I program out of hobby, not
out of necessity.
So? Ususally, even when doing it as a hobby, people tend to write programs
that do something useful.

Jul 2 '06 #20

P: n/a
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.
--

Frederick Gotham
Jul 2 '06 #21

P: n/a
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;
}
--

Frederick Gotham
Jul 2 '06 #22

P: n/a
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.
--

Frederick Gotham
Jul 2 '06 #23

P: n/a
Robbie Hatley posted:
"Frederick Gotham" <fg*******@SPAM.comwrote:
>It is possible and permissible on a given system, that the alignment
requirements of a type are less than the size of that type. For
instance, here's a hypothetical set-up:

int is 4 bytes, but need only be aligned on a 2 byte boundary.

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.
--

Frederick Gotham
Jul 2 '06 #24

P: n/a
Frederick Gotham wrote:
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.
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.

Jul 2 '06 #25

P: n/a
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.
--

Frederick Gotham
Jul 2 '06 #26

P: n/a
Frederick Gotham wrote:
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.
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.

Jul 2 '06 #27

P: n/a
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.
--

Frederick Gotham
Jul 2 '06 #28

P: n/a
* 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,
the std uss th wrd "unspcfd"

and perfectly predictable.
fr gvn cmplr

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Jul 2 '06 #29

P: n/a
In article <4g*************@individual.net>,
"Alf P. Steinbach" <al***@start.nowrote:
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.
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
Jul 2 '06 #30

P: n/a
* Howard Hinnant:
In article <4g*************@individual.net>,
"Alf P. Steinbach" <al***@start.nowrote:
>>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.

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.
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.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Jul 2 '06 #31

P: n/a
In article <4g*************@individual.net>,
"Alf P. Steinbach" <al***@start.nowrote:
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
Jul 2 '06 #32

P: n/a
Frederick Gotham wrote:
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.

One how many different processors and compilers?

--
Ian Collins.
Jul 2 '06 #33

P: n/a
Ian Collins posted:
Frederick Gotham wrote:
>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.

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.
--

Frederick Gotham
Jul 2 '06 #34

P: n/a
Frederick Gotham wrote:
Ian Collins posted:

>>Frederick Gotham wrote:
>>>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.


One how many different processors and compilers?

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.

--
Ian Collins.
Jul 2 '06 #35

P: n/a
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.

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.
--

Frederick Gotham
Jul 2 '06 #36

P: n/a
Federick Gotham wrote:
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.

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.

--
Ian Collins.
Jul 2 '06 #37

P: n/a
"Frederick Gotham" wrote:
Robbie Hatley posted:
"Frederick Gotham" <fg*******@SPAM.comwrote:
It is possible and permissible on a given system, that the alignment
requirements of a type are less than the size of that type. For
instance, here's a hypothetical set-up:

int is 4 bytes, but need only be aligned on a 2 byte boundary.
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.
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/
Jul 3 '06 #38

P: n/a
Robbie Hatley posted:

>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.)

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.

--

Frederick Gotham
Jul 3 '06 #39

P: n/a
Robbie Hatley wrote:
"Frederick Gotham" wrote:
>Robbie Hatley posted:
>>"Frederick Gotham" <fg*******@SPAM.comwrote:

It is possible and permissible on a given system, that the alignment
requirements of a type are less than the size of that type. For
instance, here's a hypothetical set-up:

int is 4 bytes, but need only be aligned on a 2 byte boundary.

How on Earth could that work?
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.
>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.
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.

Jul 3 '06 #40

This discussion thread is closed

Replies have been disabled for this discussion.