Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

standard memory allocator alignment issue...

22 views
Skip to first unread message

Chris Thomasson

unread,
May 12, 2008, 2:13:16 AM5/12/08
to
How many C compilers provide extensions which allow for a standard
implementation of the following hack?
____________________________________________________________________
#include <stdio.h>


typedef union aligner_types_u aligner_types;
typedef struct aligner_offset_s aligner_offset;


union aligner_types_u {
char char_;
short s_l;
int i_;
long l_;
double d_;
long double ld_;
float f_;
void *p_;
char (*fp0_) (char);
long double (*fp1_) (char, long double);
union aligner_types* uap_;
/* long long ll_; */
/* [...] */
};


struct aligner_offset_s {
char offset;
aligner_types types;
};


#define ALIGN_MAX ( \
sizeof(aligner_offset) > sizeof(aligner_types) \
? sizeof(aligner_offset) - sizeof(aligner_types) \
: sizeof(aligner_types) \
)


int main() {
printf("ALIGN_MAX == %d\n\nhit enter to exit...\n", ALIGN_MAX);
getchar();
return 0;
}

____________________________________________________________________

Thanks...

BTW, the ALIGN_MAX macro is needed because using a sizeof(aligner_types)
alone is not sufficient... How many people are running platforms where
(ALIGN_MAX == 8) is true?

Chris Thomasson

unread,
May 12, 2008, 2:24:31 AM5/12/08
to
"Chris Thomasson" <cri...@comcast.net> wrote in message
news:5umdnWjfo9PPQrrV...@comcast.com...

> How many C compilers provide extensions which allow for a standard
> implementation of the following hack?
[...]

Standard in the sense of being portable within the various versions of a
given vendors C compiler...

:^o

Eric Sosman

unread,
May 12, 2008, 8:14:40 AM5/12/08
to

Observation #1: It is impossible that the "else" branch
of ALIGN_MAX' expansion will be evaluated, so you might as
well just put `42' there.

Observation #2: ALIGN_MAX computes the number of bytes
in the struct, minus one for the `char' element, minus the
number of padding bytes before the union, minus the number
of padding bytes *after* the union. I've never seen a
compiler where that final term would be non-zero, but ...

Observation #3: On some platforms the program will say
"ALIGN_MAX == 0", because that's one of the likely outcomes
of the undefined behavior in the printf() call.

Observation #4: I'm not entirely sure, but I think the
"extension" you seek is the offsetof macro in <stddef.h>.

--
Eric Sosman
eso...@ieee-dot-org.invalid

Chris Thomasson

unread,
May 12, 2008, 5:41:20 PM5/12/08
to
"Eric Sosman" <eso...@ieee-dot-org.invalid> wrote in message
news:0f-dnYX0zdkuqbXV...@comcast.com...

> Chris Thomasson wrote:
>> How many C compilers provide extensions which allow for a standard
>> implementation of the following hack?
>> ____________________________________________________________________
[...]
>> ____________________________________________________________________
[...]

>> BTW, the ALIGN_MAX macro is needed because using a sizeof(aligner_types)
>> alone is not sufficient... How many people are running platforms where
>> (ALIGN_MAX == 8) is true?
>
> Observation #1: It is impossible that the "else" branch
> of ALIGN_MAX' expansion will be evaluated, so you might as
> well just put `42' there.

> Observation #2: ALIGN_MAX computes the number of bytes
> in the struct, minus one for the `char' element, minus the
> number of padding bytes before the union, minus the number
> of padding bytes *after* the union. I've never seen a
> compiler where that final term would be non-zero, but ...

> Observation #3: On some platforms the program will say
> "ALIGN_MAX == 0", because that's one of the likely outcomes
> of the undefined behavior in the printf() call.

Totally agree with everything you said. As for printf, at least I should
have it formatted for an unsigned integer: %u. ;^(

> Observation #4: I'm not entirely sure, but I think the
> "extension" you seek is the offsetof macro in <stddef.h>.

You got it:
___________________________________________________________________
#include <stdio.h>
#include <stddef.h>


typedef union aligner_types_u aligner_types;
typedef struct aligner_offset_s aligner_offset;


union aligner_types_u {
char char_; short s_l; int i_; long l_;
double d_; long double ld_; float f_;

union aligner_types* uap_;


void *p_; char (*fp0_) (char);
long double (*fp1_) (char, long double);

/* long long ll_; */
/* [...] */
};


struct aligner_offset_s {
char offset;
aligner_types types;
};


#define ALIGN_MAX offsetof(aligner_offset, types)


int main() {
printf("ALIGN_MAX == %u\n\nhit enter to exit...\n", ALIGN_MAX);
getchar();
return 0;
}
___________________________________________________________________

I am trying to come up with somewhat "portable" hack that can attempt to
determine maximum alignment for integral types across a number of different
compilers.

Chris Thomasson

unread,
May 12, 2008, 5:51:41 PM5/12/08
to
"Chris Thomasson" <cri...@comcast.net> wrote in message
news:tf-dndgJDOpIJbXV...@comcast.com...

> "Eric Sosman" <eso...@ieee-dot-org.invalid> wrote in message
> news:0f-dnYX0zdkuqbXV...@comcast.com...
>> Chris Thomasson wrote:
>>> How many C compilers provide extensions which allow for a standard
>>> implementation of the following hack?
>>> ____________________________________________________________________
> [...]
>>> ____________________________________________________________________
[...]
>> Observation #4: I'm not entirely sure, but I think the
>> "extension" you seek is the offsetof macro in <stddef.h>.
>
> You got it:
> ___________________________________________________________________
[...]
> ___________________________________________________________________

> I am trying to come up with somewhat "portable" hack that can attempt to
> determine maximum alignment for integral types across a number of
> different compilers.

I have been successfully using the previous method in several
general-purpose memory allocators. However, I wanted to see if there is a
better way; offsetof works fine. BTW, does anybody know why there is not
something like ALIGN_MAX in <limits.h> already?

Eric Sosman

unread,
May 12, 2008, 6:08:39 PM5/12/08
to
Chris Thomasson wrote:
> "Eric Sosman" <eso...@ieee-dot-org.invalid> wrote...
>> Chris Thomasson wrote:
>> [... printf with "%d" for a size_t ...]

>> Observation #3: On some platforms the program will say
>> "ALIGN_MAX == 0", because that's one of the likely outcomes
>> of the undefined behavior in the printf() call.
>
> Totally agree with everything you said. As for printf, at least I should
> have it formatted for an unsigned integer: %u. ;^(

Use "%u" *and* convert the size_t value to `unsigned int'.
(Or you can use "%zu" with a C99 library.) The particular
misbehavior I mentioned could occur on a BigEndian system
with a 64-bit size_t and a 32-bit int, where a plain "%d" or
"%u" would pick up the high-order (all-zero) half of the
double-wide size_t number ...

>> Observation #4: I'm not entirely sure, but I think the
>> "extension" you seek is the offsetof macro in <stddef.h>.
>
> You got it:

> [...]


> I am trying to come up with somewhat "portable" hack that can attempt to
> determine maximum alignment for integral types across a number of
> different compilers.

The difficulties are in enumerating all the integer types
(easy in C90, hard in C99) and in making useful manipulations
of pointers-as-integers (hard in C90, easier in C99 but still
not a walk in the park). For simple "flat" memory models the
kind of thing you're doing is straightforward, but there's the
nagging possibility that the code may find its way to a more
baroque environment ...

--
Eric....@sun.com

Eric Sosman

unread,
May 12, 2008, 6:22:03 PM5/12/08
to
Chris Thomasson wrote:
> [... determining alignment with a struct and offsetof ...]

>
> I have been successfully using the previous method in several
> general-purpose memory allocators. However, I wanted to see if there is
> a better way; offsetof works fine. BTW, does anybody know why there is
> not something like ALIGN_MAX in <limits.h> already?

The Rationale doesn't say why not. My guess (and it's only
a guess) is that the Committee didn't want to get too involved
in specifying exactly how pointers convert to and from integers.
Without knowledge of which integer bits have what significance,
you can't make effective use of things like ALIGN_MAX.

--
Eric....@sun.com

Chris Thomasson

unread,
May 12, 2008, 6:41:29 PM5/12/08
to
"Eric Sosman" <Eric....@sun.com> wrote in message
news:1210630927.374478@news1nwk...

Humm, a compiler vendor already has to supply a malloc implementation which
returns an address that is aligned on a sufficient boundary for all integral
types; right? Well, IMVHO, the standard could mention that a vendor shall
set the value of ALIGN_MAX to a sufficient boundary analogous to the
non-NULL return value of malloc which can accompany the alignment of any
integral type. The rational is that a vendor can likely extract ALIGN_MAX
from their existing malloc implementation...

Is that total crap?

;^)

Spiros Bousbouras

unread,
May 12, 2008, 7:02:41 PM5/12/08
to
On 12 May, 23:41, "Chris Thomasson" <cris...@comcast.net> wrote:
> "Eric Sosman" <Eric.Sos...@sun.com> wrote in message

If you had ALIGN_MAX what would you do with it ?

Richard Tobin

unread,
May 12, 2008, 7:13:30 PM5/12/08
to
In article <c2857956-f78b-47c9...@r66g2000hsg.googlegroups.com>,
Spiros Bousbouras <spi...@gmail.com> wrote:

>If you had ALIGN_MAX what would you do with it ?

Write an allocator that returns memory adequately aligned for any
object, perhaps.

-- Richard
--
:wq

Keith Thompson

unread,
May 12, 2008, 7:20:39 PM5/12/08
to

One thing I might do is write my own memory allocator. Call malloc()
once to get a big chunk of memory (guaranteed to be aligned properly),
then dole out properly-aligned subchunks of it in response to
my_malloc() calls. Free everything at once by free()ing the big
chunk. Without ALIGN_MAX, I can't think of a portable way to
guarantee that the pointers returned by my_malloc are properly
aligned.

--
Keith Thompson (The_Other_Keith) ks...@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"

Ian Collins

unread,
May 12, 2008, 7:22:53 PM5/12/08
to
That depends on whether the compiler supplies its own runtime, or uses
one supplied by the host environment.

--
Ian Collins.

Ian Collins

unread,
May 12, 2008, 7:32:26 PM5/12/08
to
How would this code with the situation where sizeof(long long) == 8 and
sizeof(long double) = 12? In that case, 16 would probably be a sensible
value for ALIGN_MAX. Not easy to calculate as a compile time constant.

--
Ian Collins.

Chris Thomasson

unread,
May 12, 2008, 7:36:44 PM5/12/08
to
"Ian Collins" <ian-...@hotmail.com> wrote in message
news:68s1qcF...@mid.individual.net...

Humm, good point indeed. Well, in that case, I guess the compiler can
probably make use of the ALIGN_MAX definition already residing in the
<limits.h> file provided by a "conforming" host environment, where
conforming means provides a version of the next standard which would include
ALIGN_MAX in <limits.h>)...

Chris Thomasson

unread,
May 12, 2008, 7:41:37 PM5/12/08
to
"Ian Collins" <ian-...@hotmail.com> wrote in message
news:68s2caF...@mid.individual.net...

> Chris Thomasson wrote:
>> "Eric Sosman" <eso...@ieee-dot-org.invalid> wrote in message
>> news:0f-dnYX0zdkuqbXV...@comcast.com...
>>> Chris Thomasson wrote:
[...]
>> ___________________________________________________________________

>>
>> I am trying to come up with somewhat "portable" hack that can attempt to
>> determine maximum alignment for integral types across a number of
>> different compilers.
>>
> How would this code with the situation where sizeof(long long) == 8 and
> sizeof(long double) = 12? In that case, 16 would probably be a sensible
> value for ALIGN_MAX. Not easy to calculate as a compile time constant.

On GCC for 32-bit x86 windows, sizeof(double) == 8, sizeof(long double) ==
12 and the offsetof version of ALIGN_MAX is 8. I think reasoning for result
is that 4 is suitable alignment for long double and 8 is already compatible
with boundary of 4.

Ian Collins

unread,
May 12, 2008, 7:56:18 PM5/12/08
to

Fair enough. I have used 16 for several "semi-portable" allocators. On
each platform where these were used, the native malloc also used 16.

--
Ian Collins.

Chris Torek

unread,
May 12, 2008, 8:46:18 PM5/12/08
to
>Spiros Bousbouras <spi...@gmail.com> writes:
>> If you had ALIGN_MAX what would you do with it ?

In article <lny76fk...@nuthaus.mib.org>
Keith Thompson <ks...@mib.org> wrote:
>One thing I might do is write my own memory allocator. ...

As I have noted (several times, I think) in the past, ALIGN_MAX
(or ALIGNBYTES, as we spelled it in 4.4BSD) is necessary but not
sufficient. You also need something that takes an "unaligned"
pointer and produces the "aligned version" of that pointer, or the
offset that makes it aligned. (This need only work for byte
pointers, i.e., "unsigned char *", although it is probably more
convenient if it is somehow generic.)
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: gmail (figure it out) http://web.torek.net/torek/index.html

Ben Bacarisse

unread,
May 12, 2008, 8:53:49 PM5/12/08
to
Keith Thompson <ks...@mib.org> writes:

The suggestion seems to be that ALIGN_MAX is some arithmetic value. I
can't see a way to adjust a pointer using it in any potable way. I
think this is the point behind Eric's "Without knowledge of which


integer bits have what significance, you can't make effective use of

things like ALIGN_MAX". The standard declines to say anything about
what the arithmetic value of a well-aligned pointer is.

If you are assuming that the suggestion is for a function-line macro:

#define ALIGN_MAX(p)

that behaves like a function declared void *ALIGN_MAX(void *) which
adjusts the pointer it is given, then I agree it would be possible to
write an allocator. (But I would suggest the name be lower-cased to
match things like offsetof and changed to sound less like a constant
-- another parameter might also be required to indicate "direction").

--
Ben.

Eric Sosman

unread,
May 12, 2008, 9:26:56 PM5/12/08
to
Ben Bacarisse wrote:
>
> The suggestion seems to be that ALIGN_MAX is some arithmetic value. I
> can't see a way to adjust a pointer using it in any potable way.

Ahh! That wets the whistle proper, that does! Barkeep,
another round of Jack Daniel's Old Number (1uL << ALIGN_BITS)-1
for these good people, if you please.

--
Eric Sosman
eso...@ieee-dot-org.invalid

Chris Thomasson

unread,
May 12, 2008, 10:00:01 PM5/12/08
to
"Ben Bacarisse" <ben.u...@bsb.me.uk> wrote in message
news:877idz8...@bsb.me.uk...

> Keith Thompson <ks...@mib.org> writes:
>
>> Spiros Bousbouras <spi...@gmail.com> writes:
>>> On 12 May, 23:41, "Chris Thomasson" <cris...@comcast.net> wrote:
>>>> "Eric Sosman" <Eric.Sos...@sun.com> wrote in message
>>>>
>>>> news:1210630927.374478@news1nwk...
>>>>
>>>> > Chris Thomasson wrote:
>>>> >> [... determining alignment with a struct and offsetof ...]
>>>>
>>>> >> I have been successfully using the previous method in several
>>>> >> general-purpose memory allocators.
[...]

>>>>
>>>> > The Rationale doesn't say why not. My guess (and it's only
>>>> > a guess) is that the Committee didn't want to get too involved
>>>> > in specifying exactly how pointers convert to and from integers.
>>>> > Without knowledge of which integer bits have what significance,
>>>> > you can't make effective use of things like ALIGN_MAX.
>>>>
>>>> Humm, a compiler vendor already has to supply a malloc implementation
>>>> which
>>>> returns an address that is aligned on a sufficient boundary for all
>>>> integral
>>>> types; right?
[...]

>>> If you had ALIGN_MAX what would you do with it ?
>>
>> One thing I might do is write my own memory allocator.

[...]


> The suggestion seems to be that ALIGN_MAX is some arithmetic value. I
> can't see a way to adjust a pointer using it in any potable way.

[...]


I am currently using something like the following hack to align pointers on
boundaries which are powers of 2:


__________________________________________________________________
#include <stdio.h>
#include <stddef.h>


typedef union align_detail_types_u align_detail_types;
typedef struct align_detail_offset_s align_detail_offset;


union align_detail_types_u {


char char_; short s_l; int i_; long l_;
double d_; long double ld_; float f_;

union align_types* uap_;


void *p_; char (*fp0_) (char);
long double (*fp1_) (char, long double);
/* long long ll_; */
/* [...] */
};


struct align_detail_offset_s {
char offset;
align_detail_types types;
};


typedef long int align_detail_intptr;


#define ALIGN_MAX offsetof(align_detail_offset, types)


#define ALIGN_POW2(mp_this, mp_type) ((mp_type)( \
(((align_detail_intptr const)(mp_this)) + 1) & (-2) \
))


#define ALIGN(mp_this, mp_type, mp_align) ((mp_type)( \
(((align_detail_intptr const)(mp_this)) + \
ALIGN_POW2(mp_align, align_detail_intptr const) - 1) \
& (-ALIGN_POW2(mp_align, align_detail_intptr const)) \
))


#define ALIGN_CHECK(mp_this, mp_type, mp_align) ( \
(mp_this) == ALIGN(mp_this, mp_type, mp_align) \
)


typedef char ALIGN_DETAIL_SASSERT[
(ALIGN_MAX)
&& (ALIGN_CHECK(ALIGN_MAX, size_t, 2))
&& (ALIGN_CHECK(ALIGN_MAX, size_t, sizeof(void*)))
&& (ALIGN_CHECK(ALIGN_MAX, size_t, sizeof(void* (*) (void*))))
&& (sizeof(align_detail_intptr) >= sizeof(void*))
&& (sizeof(align_detail_intptr) >= sizeof(void* (*) (void*)))
? 1 : -1
];

#define L2CACHE_SIZE 128
#define BLOCK_SIZE 4096
#define SUPERBLOCK_SIZE (BLOCK_SIZE * 8)


int main() {
unsigned char* rawbuf[(SUPERBLOCK_SIZE * 2) - 1];

unsigned char* l2cachebuf =
ALIGN(rawbuf, unsigned char*, L2CACHE_SIZE);

unsigned char* pagebuf =
ALIGN(rawbuf, unsigned char*, BLOCK_SIZE);

unsigned char* superbuf =
ALIGN(rawbuf, unsigned char*, SUPERBLOCK_SIZE);

printf("(%u) == ALIGN_MAX\n(%p) == rawbuf\n\
(%p) == l2cachebuf\n(%p) == pagebuf\n(%p) == superbuf\n",
(unsigned)ALIGN_MAX, (void*)rawbuf, (void*)l2cachebuf,
(void*)pagebuf, (void*)superbuf);

return 0;
}

__________________________________________________________________


Any suggestions on how to improve the abomination?

;^)


> If you are assuming that the suggestion is for a function-line macro:
>
> #define ALIGN_MAX(p)
>
> that behaves like a function declared void *ALIGN_MAX(void *) which
> adjusts the pointer it is given, then I agree it would be possible to
> write an allocator. (But I would suggest the name be lower-cased to
> match things like offsetof and changed to sound less like a constant
> -- another parameter might also be required to indicate "direction").

That should be workable; I like it.

Ben Bacarisse

unread,
May 12, 2008, 10:07:49 PM5/12/08
to
Eric Sosman <eso...@ieee-dot-org.invalid> writes:

> Ben Bacarisse wrote:
>>
>> The suggestion seems to be that ALIGN_MAX is some arithmetic value. I
>> can't see a way to adjust a pointer using it in any potable way.
>
> Ahh! That wets the whistle proper, that does!

*sigh* At least this one was mildly amusing. Most of my typos invert
the meaning of the text.

--
Ben.

Ben Bacarisse

unread,
May 12, 2008, 10:36:49 PM5/12/08
to
"Chris Thomasson" <cri...@comcast.net> writes:

> "Ben Bacarisse" <ben.u...@bsb.me.uk> wrote in message
> news:877idz8...@bsb.me.uk...

<snip>


> [...]
>> The suggestion seems to be that ALIGN_MAX is some arithmetic value. I

>> can't see a way to adjust a pointer using it in any po[r]table way.
<snip, but permit me to correct my typo!>


>
> I am currently using something like the following hack to align
> pointers on boundaries which are powers of 2:

<snip>
> typedef long int align_detail_intptr;
<snip>


> #define ALIGN_POW2(mp_this, mp_type) ((mp_type)( \
> (((align_detail_intptr const)(mp_this)) + 1) & (-2) \
> ))
>
>
> #define ALIGN(mp_this, mp_type, mp_align) ((mp_type)( \
> (((align_detail_intptr const)(mp_this)) + \
> ALIGN_POW2(mp_align, align_detail_intptr const) - 1) \
> & (-ALIGN_POW2(mp_align, align_detail_intptr const)) \
> ))

<snip>


> Any suggestions on how to improve the abomination?
>
> ;^)

I would document (maybe another clause in your static assert?) that
long must be able to hold a pointer (I assume you can't use C99's
intptr_t?).

You rely on the representation of -2 and of -ALIGN_POW2(...). I'd use
all unsigned types to avoid both. Other than that, I think this is
the best you can do (but I am no expert on this so you may well get
better advice shortly...).

--
Ben.

Keith Thompson

unread,
May 13, 2008, 3:46:55 AM5/13/08
to
Chris Torek <nos...@torek.net> writes:
>>Spiros Bousbouras <spi...@gmail.com> writes:
>>> If you had ALIGN_MAX what would you do with it ?
>
> In article <lny76fk...@nuthaus.mib.org>
> Keith Thompson <ks...@mib.org> wrote:
>>One thing I might do is write my own memory allocator. ...
>
> As I have noted (several times, I think) in the past, ALIGN_MAX
> (or ALIGNBYTES, as we spelled it in 4.4BSD) is necessary but not
> sufficient. You also need something that takes an "unaligned"
> pointer and produces the "aligned version" of that pointer, or the
> offset that makes it aligned. (This need only work for byte
> pointers, i.e., "unsigned char *", although it is probably more
> convenient if it is somehow generic.)

Unless, as I said, your memory allocator uses chunks allocated by
malloc().

But yes, if you want to get your memory from somewhere other than
malloc, you do need a way to generate an aligned pointer from an
unaligned one.

Keith Thompson

unread,
May 13, 2008, 12:23:10 PM5/13/08
to
Ben Bacarisse <ben.u...@bsb.me.uk> writes:
> Keith Thompson <ks...@mib.org> writes:
>> Spiros Bousbouras <spi...@gmail.com> writes:
[...]

>>> If you had ALIGN_MAX what would you do with it ?
>>
>> One thing I might do is write my own memory allocator. Call malloc()
>> once to get a big chunk of memory (guaranteed to be aligned properly),
>> then dole out properly-aligned subchunks of it in response to
>> my_malloc() calls. Free everything at once by free()ing the big
>> chunk. Without ALIGN_MAX, I can't think of a portable way to
>> guarantee that the pointers returned by my_malloc are properly
>> aligned.
>
> The suggestion seems to be that ALIGN_MAX is some arithmetic value. I
> can't see a way to adjust a pointer using it in any potable way. I
> think this is the point behind Eric's "Without knowledge of which
> integer bits have what significance, you can't make effective use of
> things like ALIGN_MAX". The standard declines to say anything about
> what the arithmetic value of a well-aligned pointer is.

Agreed. An ALIGN_MAX constant (which might typically be 8 on modern
systems) is useful only if you start with an address that you already
know is adequately aligned -- which is why I started with malloc().
It's not enough to let you write a portable malloc()-like function
from scratch.

> If you are assuming that the suggestion is for a function-line macro:
>
> #define ALIGN_MAX(p)
>
> that behaves like a function declared void *ALIGN_MAX(void *) which
> adjusts the pointer it is given, then I agree it would be possible to
> write an allocator. (But I would suggest the name be lower-cased to
> match things like offsetof and changed to sound less like a constant
> -- another parameter might also be required to indicate "direction").

Or you could have, say an alignment_offset(p) macro which, given a
char* value, gives you a small integer value you can add to it to
yield a pointer that's guaranteed to be adequately aligned.

Spiros Bousbouras

unread,
May 13, 2008, 1:53:22 PM5/13/08
to
On 12 May, 23:08, Eric Sosman <Eric.Sos...@sun.com> wrote:

> Chris Thomasson wrote:
> >
> > You got it:
> > [...]
> > I am trying to come up with somewhat "portable" hack that can attempt to
> > determine maximum alignment for integral types across a number of
> > different compilers.
>
> The difficulties are in enumerating all the integer types
> (easy in C90, hard in C99)...

Isn't it actually impossible to enumerate all the integer
types in C99 ? The standard allows extended integer
types so you have no way of knowing whether on some
platform you have a "hideously long int" which has
stricter alignment requirements than every standard
type.


Eric Sosman

unread,
May 13, 2008, 2:26:59 PM5/13/08
to

Well, "impossible" is just a special case of "hard,"
right? ;-)

I'd actually written "impossible" and then I backed
off just in case Somebody Way Smarter Than Me came up with
a nifty dodge. For example, SWSTM might produce a proof
that the alignment of uintmax_t suffices for all other
integers, too. I don't know of any such proof (even if
I did, the margin of this post would probably be too narrow
to contain it) but SWSTM might come up with something, so
I ducked the issue.

--
Eric....@sun.com


Keith Thompson

unread,
May 13, 2008, 3:32:07 PM5/13/08
to

Actually, I'm reasonably sure that uintmax_t is *not* required to have
an alignment that suffices for all other integer types.

It's even plausible that some smaller integer type might have stricter
alignment than uintmax_t. Suppose types up to 64 bits are implemented
in hardware, and each N-bit hardware type requires N-bit alignment.
Suppose uintmax_t is 128 bits, implemented in software as (the
equivalent of) an array of 4 32-bit integers, requiring only 32-bit
alignment. (Assume there's a good reason to do this rather than an
array of 2 64-bit integers).

Spiros Bousbouras

unread,
May 13, 2008, 4:29:44 PM5/13/08
to
On 13 May, 03:00, "Chris Thomasson" <cris...@comcast.net> wrote:
>
> I am currently using something like the following hack to align pointers on
> boundaries which are powers of 2:
> __________________________________________________________________
> #include <stdio.h>
> #include <stddef.h>
>
> typedef union align_detail_types_u align_detail_types;
> typedef struct align_detail_offset_s align_detail_offset;
>
> union align_detail_types_u {
> char char_; short s_l; int i_; long l_;
> double d_; long double ld_; float f_;
> union align_types* uap_;
> void *p_; char (*fp0_) (char);
> long double (*fp1_) (char, long double);
> /* long long ll_; */
> /* [...] */

Why are you using 2 function pointers , don't
all function pointers have the same alignment
requirements ?

>
> };
>
> struct align_detail_offset_s {
> char offset;
> align_detail_types types;
>
> };
>
> typedef long int align_detail_intptr;
>
> #define ALIGN_MAX offsetof(align_detail_offset, types)
>
> #define ALIGN_POW2(mp_this, mp_type) ((mp_type)( \
> (((align_detail_intptr const)(mp_this)) + 1) & (-2) \
> ))

Why are you casting to const ?

CBFalconer

unread,
May 13, 2008, 4:24:00 PM5/13/08
to
Eric Sosman wrote:
>
... snip ...

>
> I'd actually written "impossible" and then I backed
> off just in case Somebody Way Smarter Than Me came up with
> a nifty dodge. For example, SWSTM might produce a proof
> that the alignment of uintmax_t suffices for all other
> integers, too. I don't know of any such proof (even if
> I did, the margin of this post would probably be too narrow
> to contain it) but SWSTM might come up with something, so
> I ducked the issue.

I always start to put the proof of my elegant algorithms in the
margin of my notebooks, and always discover that there is
insufficient room to complete it. So I so annotate it. What's the
problem?

--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.


** Posted from http://www.teranews.com **

Eric Sosman

unread,
May 13, 2008, 5:11:24 PM5/13/08
to
CBFalconer wrote:
> Eric Sosman wrote:
> ... snip ...
>> I'd actually written "impossible" and then I backed
>> off just in case Somebody Way Smarter Than Me came up with
>> a nifty dodge. For example, SWSTM might produce a proof
>> that the alignment of uintmax_t suffices for all other
>> integers, too. I don't know of any such proof (even if
>> I did, the margin of this post would probably be too narrow
>> to contain it) but SWSTM might come up with something, so
>> I ducked the issue.
>
> I always start to put the proof of my elegant algorithms in the
> margin of my notebooks, and always discover that there is
> insufficient room to complete it. So I so annotate it. What's the
> problem?

<off-topic>

My fear is that if I put an incomplete proof in the margin
it will turn out to be my Last Theorem -- and I DON' WANNA DIE!

</off-topic>

Richard Heathfield

unread,
May 13, 2008, 6:07:53 PM5/13/08
to
Eric Sosman said:

<snip>


>
> My fear is that if I put an incomplete proof in the margin
> it will turn out to be my Last Theorem -- and I DON' WANNA DIE!

G H Hardy was once obliged to take a boat trip about which he was feeling
rather nervous. So he sent a postcard to a mathematician friend, claiming
to have proved the Riemann Hypothesis and promising details upon his safe
return. Hardy (an ardent atheist) reasoned that God wouldn't allow him to
gain eternal fame in such a deceitful way, and would therefore ensure the
safety of the vessel.

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999

Chris Thomasson

unread,
May 29, 2008, 2:57:44 AM5/29/08
to
"Keith Thompson" <ks...@mib.org> wrote in message
news:lnhcd2k...@nuthaus.mib.org...

> Ben Bacarisse <ben.u...@bsb.me.uk> writes:
>> Keith Thompson <ks...@mib.org> writes:
>>> Spiros Bousbouras <spi...@gmail.com> writes:
> [...]
>>>> If you had ALIGN_MAX what would you do with it ?
>>>
>>> One thing I might do is write my own memory allocator. Call malloc()
>>> once to get a big chunk of memory (guaranteed to be aligned properly),
>>> then dole out properly-aligned subchunks of it in response to
>>> my_malloc() calls. Free everything at once by free()ing the big
>>> chunk. Without ALIGN_MAX, I can't think of a portable way to
>>> guarantee that the pointers returned by my_malloc are properly
>>> aligned.
>>
>> The suggestion seems to be that ALIGN_MAX is some arithmetic value. I
>> can't see a way to adjust a pointer using it in any potable way. I
>> think this is the point behind Eric's "Without knowledge of which
>> integer bits have what significance, you can't make effective use of
>> things like ALIGN_MAX". The standard declines to say anything about
>> what the arithmetic value of a well-aligned pointer is.
>
> Agreed. An ALIGN_MAX constant (which might typically be 8 on modern
> systems) is useful only if you start with an address that you already
> know is adequately aligned -- which is why I started with malloc().
> It's not enough to let you write a portable malloc()-like function
> from scratch.
[...]

Exactly Right! However, that limitation is fairly trivial. You cannot create
a standard malloc with C. However, with something like ALIGN_MAX, one could
certainly create a 100% standard general-purpose custom allocation scheme
directly on top of malloc. Perhaps, one could create something that is
faster than malloc, and completely standard, for their specific problem
domains. Your correct in that ALIGN_MAX and the standard malloc call would
go hand-in-hand... Am I misrepresenting you here?

AFAICT, using malloc to retrieve a standard base, and ALIGN_MAX to round
offset calculations off to would work perfectly... For instance, a 100%
standard region-allocator can look like:

<pseudo-code sketch>
_________________________________________________________________
#include <stdlib.h>
#include <stddef.h>
#include <limits.h>

#define REGION_HEAPSIZE 8192

struct region {
char* heap; /* init with `malloc(REGION_HEAPSIZE);' */
size_t offset; /* init to zero */
};

static void* region_alloc(
struct region* const _this,
size_t size
) {
size_t const offset = _this->offset;
size = ROUND_UP(size, ALIGN_MAX);
if (offset + size > REGION_HEAPSIZE) {
return NULL;
}
_this->offset = offset + size;
return _this->heap + offset;
}

static void region_reset(
struct region* const _this
) {
_this->offset = 0;
}
_________________________________________________________________

This could be 100% standard with ALIGN_MAX... What do you think? Is that
Kosher?

Chris Thomasson

unread,
May 29, 2008, 3:02:17 AM5/29/08
to

"Chris Thomasson" <cri...@comcast.net> wrote in message
news:aZGdnab_f4cizqPV...@comcast.com...
[...]

> <pseudo-code sketch>
> _________________________________________________________________
> #include <stdlib.h>
> #include <stddef.h>
> #include <limits.h>
>
> #define REGION_HEAPSIZE 8192
>
> struct region {
> char* heap; /* init with `malloc(REGION_HEAPSIZE);' */
> size_t offset; /* init to zero */
> };
>
> static void* region_alloc(
> struct region* const _this,
> size_t size
> ) {
> size_t const offset = _this->offset;
> size = ROUND_UP(size, ALIGN_MAX);

assert(! (size % ALIGN_MAX));

of course; just for "sanity" check! ;^)

0 new messages