A portable way of pointer alignment

S

s_tec

I am missing something here. How do I use the macro above to align:

char temp[12287];

on a 4096 byte boundary? Here is what I am trying to do:

#define ALIGN(p, base, align) (base + (p - base + (align-1) & ~(align-1)))

char buffer[12287];
char* align = ALIGN(buffer, buffer, 4096);

if (((size_t)align) % 4096)
{
    puts("NOT ALIGNED");

}

I am getting NOT ALIGNED output which means the align pointer to not
aligned. What am I doing wrong?

Thanks!

I am sorry, but the macro I gave is not intended to solve your
problem. As I wrote in my description, this only works if the memory
buffer comes from new[], and only works if you want an alignment less
than or equal to the alignment new[] already provides. Your example
does not meet either of these criteria. Yes, those criteria may seem
excessively restrictive, but there are cases where they do apply.

-William "s_tec" Swanson
 
S

s_tec

What about something like this:

http://pastebin.org/96326

?

That is a reasonable solution, and is similar to what I use in real
life (except that I mainly work in C these days).

On the other hand, the core alignment calculation of "return (T*)
((((uintptr_type)ptr) + result - 1) & ((uintptr_type)(-result)));" is
not guaranteed to work on _every_ platform. Casting a pointer to an
integer gives strange results on some exotic hardware. If you care
about that (and most people don't), the calculation my ALIGN() macro
will continue to work even in these situations.

On the other hand, my calculation comes at the heavy price of having
to obtain the memory from new[] and being unable to obtain an
alignment larger than what new[] provides initially. There are some
applications that meet these crazy requirements, like allocating a
large chunk and chopping it up into smaller bits with differing
alignment requirements.

Given those restrictions, I would say that my ALIGN() macro is more of
an academic curiosity than a practical solution. As I mentioned
earlier, my own code uses the same basic alignment calculation as
yours. We don't ship our software on any oddball platforms, so things
work just fine. I just wanted to throw my solution out there in case
somebody who does care about these issues might be able to use it.

-William "s_tec" Swanson
 
C

Chris M. Thomasson

FWIW, check out this simple macro:
_________________________________________________
#define ALIGN_OF(mp_type) \
offsetof( \
struct \
{ \
char pad_ALIGN_OF; \
mp_type type_ALIGN_OF; \
}, \
type_ALIGN_OF \
)
_________________________________________________


Absent any "weird padding schemes", it should return the minimum alignment
of the given type.



On the other hand, the core alignment calculation of "return (T*)
((((uintptr_type)ptr) + result - 1) & ((uintptr_type)(-result)));" is
not guaranteed to work on _every_ platform. Casting a pointer to an
integer gives strange results on some exotic hardware. If you care
about that (and most people don't), the calculation my ALIGN() macro
will continue to work even in these situations.

Right.

[...]
 
R

red floyd

FWIW, check out this simple macro:
_________________________________________________
#define ALIGN_OF(mp_type) \
    offsetof( \
        struct \
        { \
              char pad_ALIGN_OF; \
              mp_type type_ALIGN_OF; \
        }, \
        type_ALIGN_OF \
    )

Or, if you don't want a macro:

template<typename T>
size_t align_of()
{
struct aligner
{
char pad;
T aligned;
};

return offsetof(aligner, aligned);
}
 
C

Chris M. Thomasson

Or, if you don't want a macro:

template<typename T>
size_t align_of()
{
struct aligner
{
char pad;
T aligned;
};

return offsetof(aligner, aligned);
}


Ahh, I should of clarified that the macro I presented is what I use in C.
Unfortunately, The template you have will only work with POD.
 
S

s_tec

FWIW, check out this simple macro:
_________________________________________________
#define ALIGN_OF(mp_type) \
    offsetof( \
        struct \
        { \
              char pad_ALIGN_OF; \
              mp_type type_ALIGN_OF; \
        }, \
        type_ALIGN_OF \
    )
_________________________________________________

This is really helpful. My code already uses the same basic technique,
but I did not realize there was a way to pack it into a single-line
macro like this. That will really simplify some stuff, so thanks!

-William "s_tec" Swanson
 
A

Alf P. Steinbach

* s_tec:
This is really helpful. My code already uses the same basic technique,
but I did not realize there was a way to pack it into a single-line
macro like this. That will really simplify some stuff, so thanks!

I posted essentially the same solution but as a C++ function template and with
an additional alignment helper function as the very first response in this thread.

Then instead of ALIGN_OF( Type ) you write alignmentOf<Type>()...

Reposting that:


<code>
typedef ptrdiff_t Size;

template< typename T >
inline Size alignmentOf()
{
struct X
{
char bah;
T t;
};

return offsetof( X, t );
}

template <typename T>
T* align( char* const buf, Size const bufSize)
{
Size const i = reinterpret_cast<Size>( buf );
Size const j = i + alignmentOf<T>() - 1;
Size const aligned = j - j % alignmentOf<T>();

return (aligned - i >= bufSize - sizeof(T)? 0 : reinterpret_cast<T*>(
aligned ) );
}
</code>


Then I added a disclaimer about "not tested", but it was discussed and as I
recall it was OK.


Cheers,

- Alf
 
C

Chris M. Thomasson

Alf P. Steinbach said:
* s_tec:

I posted essentially the same solution but as a C++ function template and
with an additional alignment helper function as the very first response in
this thread.

Then instead of ALIGN_OF( Type ) you write alignmentOf<Type>()...

Reposting that:


<code>
typedef ptrdiff_t Size;

template< typename T >
inline Size alignmentOf()
{
struct X
{
char bah;
T t;
};

return offsetof( X, t );
}


I don't think `offsetof()' works with POD. I also believe that it has a
problem with reference types.
 
C

Chris M. Thomasson

Chris M. Thomasson said:
I don't think `offsetof()' works with POD.

YIKES! I meant to say:

I don't think `offsetof()' works with non-POD types.


;^o
 
C

Chris M. Thomasson

This is really helpful. My code already uses the same basic technique,
but I did not realize there was a way to pack it into a single-line
macro like this. That will really simplify some stuff, so thanks!

No problem at all William.

:^D
 
A

Alf P. Steinbach

* Chris M. Thomasson:
YIKES! I meant to say:

I don't think `offsetof()' works with non-POD types.


;^o

Formally it doesn't, in practice it may and probably will, depending on the
compiler.

After all there's not much magic underneath.

Of course that also applies to the macro that you posted. :)


Hm?


Cheers,

- Alf
 
C

Chris M. Thomasson

Alf P. Steinbach said:
* Chris M. Thomasson:
Chris M. Thomasson said:
news:[email protected]... [...]
Reposting that:


<code>
typedef ptrdiff_t Size;

template< typename T >
inline Size alignmentOf()
{
struct X
{
char bah;
T t;
};

return offsetof( X, t );
}


I don't think `offsetof()' works with POD.

YIKES! I meant to say:

I don't think `offsetof()' works with non-POD types.


;^o

Formally it doesn't, in practice it may and probably will, depending on
the compiler.

After all there's not much magic underneath.

Of course that also applies to the macro that you posted. :)

Well, I only use that macro in C where everything is a POD. For C++ I use
something like:


http://pastebin.org/96326


Which seems to be working fine for everything I throw at it so far,
including reference types.




For instance, I cannot get the following to compile and run correctly:
___________________________________________________________
#include <cstddef>
#include <iostream>


template< typename T >
inline std::size_t alignmentOf()
{
struct X
{
char bah;
T t;
};

return offsetof( X, t );
}


struct object
{
char m_1[2];
double m_d[6];
long m_2[2];
short m_3[14];
};


int
main()
{
std::cout << "alignmentOf<object&> == "
<< alignmentOf<object&>()
<< std::endl;

return 0;
}
___________________________________________________________




On Comeau I get:
___________________________________________________________
Comeau C/C++ 4.3.10.1 (Oct 6 2008 11:28:09) for ONLINE_EVALUATION_BETA2
Copyright 1988-2008 Comeau Computing. All rights reserved.
MODE:strict errors C++ C++0x_extensions

"ComeauTest.c", line 8: warning: class "X" defines no constructor to
initialize the
following:
reference member "X::t"
struct X
^
detected during instantiation of
"size_t alignmentOf<T>() [with T=object &]" at line 32

"ComeauTest.c", line 14: error: expression must have a constant value
return offsetof( X, t );
^
detected during instantiation of
"size_t alignmentOf<T>() [with T=object &]" at line 32

1 error detected in the compilation of "ComeauTest.c".
___________________________________________________________




For MingW 3.4.5 I get the following warnings:
___________________________________________________________
In function `size_t alignmentOf() [with T = object&]':

instantiated from here

[Warning] invalid access to non-static data member `alignmentOf() [with T =
object&]::X::t' of NULL object

[Warning] (perhaps the `offsetof' macro was used incorrectly)
___________________________________________________________




Then when I run the program, it crashes. What am I doing wrong here Alf?
 
I

Ian Collins

Chris said:
Well, I only use that macro in C where everything is a POD. For C++ I
use something like:

http://pastebin.org/96326

Which seems to be working fine for everything I throw at it so far,
including reference types.

C doesn't have reference types.
For instance, I cannot get the following to compile and run correctly:

Then when I run the program, it crashes. What am I doing wrong here Alf?

Remember you can't dynamically allocate reference types, so they aren't
applicable to the original question.

Alf's function (or your macro) won't work with reference types because
the dummy struct has a reference member but no constructor.
 
A

Alf P. Steinbach

* Chris M. Thomasson:
Alf P. Steinbach said:
* Chris M. Thomasson:
[...]
Reposting that:


<code>
typedef ptrdiff_t Size;

template< typename T >
inline Size alignmentOf()
{
struct X
{
char bah;
T t;
};

return offsetof( X, t );
}


I don't think `offsetof()' works with POD.

YIKES! I meant to say:

I don't think `offsetof()' works with non-POD types.


;^o

Formally it doesn't, in practice it may and probably will, depending
on the compiler.

After all there's not much magic underneath.

Of course that also applies to the macro that you posted. :)

Well, I only use that macro in C where everything is a POD. For C++ I
use something like:


http://pastebin.org/96326


Which seems to be working fine for everything I throw at it so far,
including reference types.

Yah, it's better :), because it's simpler & more well-defined.

I wonder whether the constructor you put in there is really necessary though.

At first glance apparently it supports non-default-constructible type T by
assuming that T is copy constructible. But thinking about it, what it does seems
to be to limit T to copy constructible types. So how about, if the compiler
really insists on some constructor, just /declaring/ a default constructor and
not implementing, like

struct object
{
T m_object;
object();
};

After all, you'll never create any actual instance of this class?


For instance, I cannot get the following to compile and run correctly:
___________________________________________________________
#include <cstddef>
#include <iostream>


template< typename T >
inline std::size_t alignmentOf()
{
struct X
{
char bah;
T t;
};

return offsetof( X, t );
}


struct object
{
char m_1[2];
double m_d[6];
long m_2[2];
short m_3[14];
};


int
main()
{
std::cout << "alignmentOf<object&> == "
<< alignmentOf<object&>()
<< std::endl;

return 0;
}
___________________________________________________________




On Comeau I get:
___________________________________________________________
Comeau C/C++ 4.3.10.1 (Oct 6 2008 11:28:09) for ONLINE_EVALUATION_BETA2
Copyright 1988-2008 Comeau Computing. All rights reserved.
MODE:strict errors C++ C++0x_extensions

"ComeauTest.c", line 8: warning: class "X" defines no constructor to
initialize the
following:
reference member "X::t"
struct X
^
detected during instantiation of
"size_t alignmentOf<T>() [with T=object &]" at line 32

"ComeauTest.c", line 14: error: expression must have a constant value
return offsetof( X, t );
^
detected during instantiation of
"size_t alignmentOf<T>() [with T=object &]" at line 32

1 error detected in the compilation of "ComeauTest.c".
___________________________________________________________




For MingW 3.4.5 I get the following warnings:
___________________________________________________________
In function `size_t alignmentOf() [with T = object&]':

instantiated from here

[Warning] invalid access to non-static data member `alignmentOf() [with
T = object&]::X::t' of NULL object

[Warning] (perhaps the `offsetof' macro was used incorrectly)
___________________________________________________________




Then when I run the program, it crashes. What am I doing wrong here Alf?

Using a reference?

<g>

My hm was more like, why would you want to deal with that case?



Cheers,

- Alf
 
C

Chris M. Thomasson

Ian Collins said:
C doesn't have reference types.

I know. I only use the macro in C. I use the following for C++:

http://pastebin.org/96326



Remember you can't dynamically allocate reference types, so they aren't
applicable to the original question.

You can dynamically allocate objects that contain references. Anyway,
dynamic memory allocation is not the issue here. It's aligning objects. So,
if I had say:


struct object
{
int& m_int;

object(int& int_) : m_int(int_) {}
};


and a buffer:


char buffer[1024];


and I wanted to carve objects out of that buffer. Given that, I would need
to be able to get the alignment of the reference type `object::m_int'. So,
here is a program that can solve the problem by using my alignment
technique:
__________________________________________________________________________
#include <cstddef>


#if ! defined (ALIGN_UINTPTR_TYPE)
# define ALIGN_UINTPTR_TYPE std::size_t
#endif


template<typename T, std::size_t A = 0>
class align
{
typedef ALIGN_UINTPTR_TYPE uintptr_type;


typedef char sassert
[
sizeof(uintptr_type) == sizeof(void*) ? 1 : -1
];


struct object
{
T m_object;
object(T o) : m_object(o) {}
};


struct aligner
{
char m_pad;
object m_object;
};



public:
enum constant
{
result = (! A) ? (sizeof(aligner) - sizeof(object)) : A,
bufsize = result + sizeof(object) - 1
};


struct address
{
static T* calc(void* ptr)
{
return (T*)((((uintptr_type)ptr) + result - 1) &
((uintptr_type)(-result)));
}


static T const* calc(void const* ptr)
{
return (T const*)((((uintptr_type)ptr) + result - 1) &
((uintptr_type)(-result)));
}
};
};


#define ALIGN_OF(T) align<T>::result




#include <iostream>
#include <new>


struct object
{
int& m_int;
object(int& int_) : m_int(int_) {}
};


int
main()
{
int x = -666;
char raw_buffer[1024];
object* align_buffer = align<object>::address::calc(raw_buffer);
object* obj = new (align_buffer) object(x);

obj->m_int = 42;

std::cout << "ALIGN_OF(object) == " << ALIGN_OF(object) << std::endl;
std::cout << "raw_buffer == " << (void*)raw_buffer << std::endl;
std::cout << "align_buffer == " << align_buffer << std::endl;

std::cout << "x == " << x << std::endl;

return 0;
}
__________________________________________________________________________



This is example of where I might need the alignment of a reference type...



Alf's function (or your macro) won't work with reference types because the
dummy struct has a reference member but no constructor.

I still cannot get it to compile even if I add a dummy constructor:
_______________________________________________________________
#include <cstddef>
#include <iostream>


template< typename T >
inline std::size_t alignmentOf()
{
struct X
{
char bah;
T t;

X(T t_) : t(t_) {}
};

return offsetof( X, t );
}


struct object
{
char m_1[2];
double m_d[6];
long m_2[2];
short m_3[14];
};


int
main()
{
std::cout << "alignmentOf<object&> == "
<< alignmentOf<object&>()
<< std::endl;

return 0;
}
_______________________________________________________________




I get the following from Comeau:
_______________________________________________________________
Comeau C/C++ 4.3.10.1 (Oct 6 2008 11:28:09) for ONLINE_EVALUATION_BETA2
Copyright 1988-2008 Comeau Computing. All rights reserved.
MODE:strict errors C++ C++0x_extensions

"ComeauTest.c", line 16: error: expression must have a constant value
return offsetof( X, t );
^
detected during instantiation of
"size_t alignmentOf<T>() [with T=object &]" at line 34

1 error detected in the compilation of "ComeauTest.c".
_______________________________________________________________



Humm...
 
C

Chris M. Thomasson

Alf P. Steinbach said:
* Chris M. Thomasson: [...]
Well, I only use that macro in C where everything is a POD. For C++ I use
something like:


http://pastebin.org/96326


Which seems to be working fine for everything I throw at it so far,
including reference types.

Yah, it's better :), because it's simpler & more well-defined.

I wonder whether the constructor you put in there is really necessary
though.

At first glance apparently it supports non-default-constructible type T by
assuming that T is copy constructible. But thinking about it, what it does
seems to be to limit T to copy constructible types. So how about, if the
compiler really insists on some constructor, just /declaring/ a default
constructor and not implementing, like

struct object
{
T m_object;
object();
};

After all, you'll never create any actual instance of this class?

Great catch Alf! I was only implementing that dummy constructor to make the
damn compiler shut up. Declaring a default constructor is making the
compiler be quiet as well. However, I noticed that the code still works
as-is even if the object represented by `T' has private unimplemented copy
and assignment operators.


Bottom line: I like your idea of using an default constructor declaration
much better so here is the revised code:

http://pastebin.org/97533


Thanks! :^)



I also believe that it has a problem with reference types.

Hm?

For instance, I cannot get the following to compile and run correctly:
___________________________________________________________ [...]
Then when I run the program, it crashes. What am I doing wrong here Alf?

Using a reference?
;^)




My hm was more like, why would you want to deal with that case?

See my response to Ian. It may be contrived, but it shows a case in which
you would need to calculate the alignment of a reference type.
 
C

Chris M. Thomasson

Chris M. Thomasson said:
Remember you can't dynamically allocate reference types, so they aren't
applicable to the original question.

You can dynamically allocate objects that contain references. [...]
__________________________________________________________________________



This is example of where I might need the alignment of a reference type...

Ahhh. I think I just made a false point here. I am not determining the
alignment of a "pure" reference type. Instead, I am calculating the
alignment of an object that happens to contain a reference type. Well, you
make a good point Ian. I am having trouble thinking of how I can use the
alignment of a pure reference type!

;^o
 
C

Chris M. Thomasson

Alf P. Steinbach said:
* Chris M. Thomasson:
Chris M. Thomasson said:
news:[email protected]... [...]
Reposting that: [...]
I don't think `offsetof()' works with POD.

YIKES! I meant to say:

I don't think `offsetof()' works with non-POD types.


;^o

Formally it doesn't, in practice it may and probably will, depending on
the compiler.

I am getting some warnings, however the end result seems perfectly fine with
me:
_________________________________________________________________
#include <cstddef>
#include <iostream>


template< typename T >
inline std::size_t alignmentOf()
{
struct X
{
char bah;
T t;
};

return offsetof( X, t );
}


struct object_base
{
char m_1[2];
double m_d[6];
long m_2[2];
short m_3[14];

virtual void foo() = 0;
};


struct object : public object_base
{
char m_1x[2];

void foo()
{

}
};


int
main()
{
std::cout << "alignmentOf<object> == "
<< alignmentOf<object>()
<< std::endl;

return 0;
}
_________________________________________________________________




Here are the warnings from gcc:
_________________________________________________________________
In function `size_t alignmentOf() [with T = object]':
instantiated from here
[Warning] invalid access to non-static data member `alignmentOf() [with T =
object]::X::t' of NULL object
[Warning] (perhaps the `offsetof' macro was used incorrectly)
_________________________________________________________________





Still, I am a bit weary of using `offsetof()' on a non-POD type. Perhaps I
am just way to paranoid!

;^D
 
I

Ian Collins

Chris said:
Chris M. Thomasson said:
Remember you can't dynamically allocate reference types, so they
aren't applicable to the original question.

You can dynamically allocate objects that contain references. [...]
__________________________________________________________________________




This is example of where I might need the alignment of a reference
type...

Ahhh. I think I just made a false point here. I am not determining the
alignment of a "pure" reference type. Instead, I am calculating the
alignment of an object that happens to contain a reference type. Well,
you make a good point Ian. I am having trouble thinking of how I can use
the alignment of a pure reference type!

Don't think too hard!
 

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,968
Messages
2,570,154
Members
46,702
Latest member
LukasConde

Latest Threads

Top