Alignment

Discussion in 'C++' started by better_cs_now@yahoo.com, Feb 26, 2009.

  1. Guest

    Hello All,

    Please consider the two definitions below:

    Foo foo;
    unsigned char foo[sizeof(Foo)];

    Are these guaranteed to have the same alignment, or will the second
    definition have an alignment that is only modulo 1?

    Thanks,
    Dave
    , Feb 26, 2009
    #1
    1. Advertising

  2. On Feb 26, 7:00 pm, ""
    <> wrote:
    > Foo foo;
    > unsigned char foo[sizeof(Foo)];
    >
    > Are these guaranteed to have the same alignment, or will the second
    > definition have an alignment that is only modulo 1?


    The standard has the answer in 3.1-5 [basic.types]:

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

    So, unless your Foo is a typedef for an array of unsigned char, then
    your foo objects are two different types. Therefore both have their
    own implementation-defined alignment en you can not portably assume
    they will be the same.
    Gert-Jan de Vos, Feb 26, 2009
    #2
    1. Advertising

  3. Guest

    On Feb 26, 11:18 am, Gert-Jan de Vos <gert-
    > wrote:
    > On Feb 26, 7:00 pm, ""
    >
    > <> wrote:
    > > Foo foo;
    > > unsigned char foo[sizeof(Foo)];

    >
    > > Are these guaranteed to have the same alignment, or will the second
    > > definition have an alignment that is only modulo 1?

    >
    > The standard has the answer in 3.1-5 [basic.types]:
    >
    > "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."
    >
    > So, unless your Foo is a typedef for an array of unsigned char, then
    > your foo objects are two different types. Therefore both have their
    > own implementation-defined alignment en you can not portably assume
    > they will be the same.


    To force the unsigned char array to have the same alignment as the Foo
    (which is my goal), I'd like to put these together in a union.
    However, Foo has a non-trivial constructor, so it may not be a member
    of a union. Do I have any othre options?

    Thanks to all!
    , Feb 26, 2009
    #3
  4. peter koch Guest

    On 26 Feb., 19:36, wrote:
    > On Feb 26, 11:18 am, Gert-Jan de Vos <gert-
    >
    >
    >
    >
    >
    > > wrote:
    > > On Feb 26, 7:00 pm, ""

    >
    > > <> wrote:
    > > > Foo foo;
    > > > unsigned char foo[sizeof(Foo)];

    >
    > > > Are these guaranteed to have the same alignment, or will the second
    > > > definition have an alignment that is only modulo 1?

    >
    > > The standard has the answer in 3.1-5 [basic.types]:

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

    >
    > > So, unless your Foo is a typedef for an array of unsigned char, then
    > > your foo objects are two different types. Therefore both have their
    > > own implementation-defined alignment en you can not portably assume
    > > they will be the same.

    >
    > To force the unsigned char array to have the same alignment as the Foo
    > (which is my goal), I'd like to put these together in a union.
    > However, Foo has a non-trivial constructor, so it may not be a member
    > of a union. Do I have any othre options?


    Yes. Search this group and the moderated one for a solution that will
    give the correct alignment (basically: a union containing all possible
    types and the char representation).

    /Peter
    peter koch, Feb 26, 2009
    #4
  5. Greg Herlihy Guest

    On Feb 26, 10:36 am, wrote:
    > On Feb 26, 11:18 am, Gert-Jan de Vos <gert-
    >
    > To force the unsigned char array to have the same alignment as the Foo
    > (which is my goal), I'd like to put these together in a union.
    > However, Foo has a non-trivial constructor, so it may not be a member
    > of a union. Do I have any othre options?


    Allocate the char array dynamically:

    char * fooArray = new char[sizeof(Foo)];

    Now fooArray will be suitably aligned for a Foo type.

    Greg
    Greg Herlihy, Feb 26, 2009
    #5
  6. Guest

    On Feb 26, 12:11 pm, Greg Herlihy <> wrote:
    > On Feb 26, 10:36 am, wrote:
    >
    > > On Feb 26, 11:18 am, Gert-Jan de Vos <gert-

    >
    > > To force the unsigned char array to have the same alignment as the Foo
    > > (which is my goal), I'd like to put these together in a union.
    > > However, Foo has a non-trivial constructor, so it may not be a member
    > > of a union. Do I have any othre options?

    >
    > Allocate the char array dynamically:
    >
    >    char * fooArray = new char[sizeof(Foo)];
    >
    > Now fooArray will be suitably aligned for a Foo type.
    >
    > Greg


    Unfortunately, allocating on the heap is verboten in our application.
    Whether it makes sense or not, it is what it is and it will not pass
    the design review.

    The memory I'm trying to get properly aligned is actually going to be
    static in a class and will have a singleton instance of the class
    constructed in it via placement new.

    class Foo
    {
    ...
    static unsigned char s_pInstance[];
    };

    unsigned char Foo::s_pInstance[sizeof(Foo)]; // Will have a Foo
    constructed in it

    The goal is to ensure that s_pInstance is suitably aligned to hold a
    Foo. Is this possible within the bounds of the C++ language standard,
    or is it an architecture issue (in which case I'm in the wrong group)?
    , Feb 26, 2009
    #6
  7. Guest

    On Feb 26, 12:11 pm, Greg Herlihy <> wrote:
    > On Feb 26, 10:36 am, wrote:
    >
    > > On Feb 26, 11:18 am, Gert-Jan de Vos <gert-

    >
    > > To force the unsigned char array to have the same alignment as the Foo
    > > (which is my goal), I'd like to put these together in a union.
    > > However, Foo has a non-trivial constructor, so it may not be a member
    > > of a union. Do I have any othre options?

    >
    > Allocate the char array dynamically:
    >
    >    char * fooArray = new char[sizeof(Foo)];
    >
    > Now fooArray will be suitably aligned for a Foo type.
    >
    > Greg


    In addition to my prvious response a minute ago, your comment brings
    up a side issue.

    In my original post, I showed the Foo and the char array being
    constructed off of the heap, and the response was that the alignment I
    seek is not guaranteed. However, your response clearly states that the
    alignment I seek *will* be guaranteed if they are constructed on the
    heap. So, I'd like to reconfirm -- are alignment issues indeed treated
    differently on the heap than off?

    Thanks for the response!
    , Feb 26, 2009
    #7
  8. Bo Persson Guest

    wrote:
    > On Feb 26, 12:11 pm, Greg Herlihy <> wrote:
    >> On Feb 26, 10:36 am, wrote:
    >>
    >>> On Feb 26, 11:18 am, Gert-Jan de Vos <gert-

    >>
    >>> To force the unsigned char array to have the same alignment as
    >>> the Foo (which is my goal), I'd like to put these together in a
    >>> union. However, Foo has a non-trivial constructor, so it may not
    >>> be a member of a union. Do I have any othre options?

    >>
    >> Allocate the char array dynamically:
    >>
    >> char * fooArray = new char[sizeof(Foo)];
    >>
    >> Now fooArray will be suitably aligned for a Foo type.
    >>
    >> Greg

    >
    > In addition to my prvious response a minute ago, your comment brings
    > up a side issue.
    >
    > In my original post, I showed the Foo and the char array being
    > constructed off of the heap, and the response was that the
    > alignment I seek is not guaranteed. However, your response clearly
    > states that the alignment I seek *will* be guaranteed if they are
    > constructed on the heap. So, I'd like to reconfirm -- are alignment
    > issues indeed treated differently on the heap than off?
    >
    > Thanks for the response!


    No, the "trick" is the use of the global operator new,

    void* operator new(std::size_t size) throw(std::bad_alloc);

    which is required to allocate bytes "suitably aligned to represent any
    object of that size".

    Note that the operator doesn't know the type of the object, but must
    still obey the rule. We don't know how!


    Bo Persson
    Bo Persson, Feb 26, 2009
    #8
  9. On Feb 26, 8:29 pm, wrote:
    > On Feb 26, 12:11 pm, Greg Herlihy <> wrote:
    > > Allocate the char array dynamically:

    >
    > >    char * fooArray = new char[sizeof(Foo)];

    >
    > > Now fooArray will be suitably aligned for a Foo type.

    >
    > > Greg

    >
    > In addition to my previous response a minute ago, your comment brings
    > up a side issue.
    >
    > In my original post, I showed the Foo and the char array being
    > constructed off of the heap, and the response was that the alignment I
    > seek is not guaranteed. However, your response clearly states that the
    > alignment I seek *will* be guaranteed if they are constructed on the
    > heap. So, I'd like to reconfirm -- are alignment issues indeed treated
    > differently on the heap than off?


    If you are after a singleton implementation that doesn't use the heap,
    why not use Meyers singleton?

    The standard specifically states that new array of char or unsigned
    char provides correct alignment for any object that fits in the
    requested size. This explicitly allows what you are after, except that
    it needs heap storage.
    Gert-Jan de Vos, Feb 26, 2009
    #9
  10. Guest

    On Feb 26, 12:50 pm, Gert-Jan de Vos <gert-
    > wrote:
    > On Feb 26, 8:29 pm, wrote:
    >
    >
    >
    >
    >
    > > On Feb 26, 12:11 pm, Greg Herlihy <> wrote:
    > > > Allocate the char array dynamically:

    >
    > > >    char * fooArray = new char[sizeof(Foo)];

    >
    > > > Now fooArray will be suitably aligned for a Foo type.

    >
    > > > Greg

    >
    > > In addition to my previous response a minute ago, your comment brings
    > > up a side issue.

    >
    > > In my original post, I showed the Foo and the char array being
    > > constructed off of the heap, and the response was that the alignment I
    > > seek is not guaranteed. However, your response clearly states that the
    > > alignment I seek *will* be guaranteed if they are constructed on the
    > > heap. So, I'd like to reconfirm -- are alignment issues indeed treated
    > > differently on the heap than off?

    >
    > If you are after a singleton implementation that doesn't use the heap,
    > why not use Meyers singleton?
    >
    > The standard specifically states that new array of char or unsigned
    > char provides correct alignment for any object that fits in the
    > requested size. This explicitly allows what you are after, except that
    > it needs heap storage.- Hide quoted text -
    >
    > - Show quoted text -


    I had started with the Meyers singleton, but the problem I quickly ran
    into was losing control over the sequence in which my singletons are
    destructed. I have a lot of singletons, and there are dependencies
    among them. So I must maintain control over their destruction order.
    Having them constructed as static objects (i.e. as Meyers singletons)
    deprives me of that control.
    , Feb 26, 2009
    #10
  11. <> wrote in message
    news:...
    > Hello All,
    >
    > Please consider the two definitions below:
    >
    > Foo foo;
    > unsigned char foo[sizeof(Foo)];
    >
    > Are these guaranteed to have the same alignment, or will the second
    > definition have an alignment that is only modulo 1?


    You can attempt to calculate alignment of `Foo' objects like this:
    ___________________________________________________________________
    #include <cstddef>
    #include <cstdio>


    struct Foo {
    char a;
    int b;
    double c;

    Foo(int b) {
    // [...];
    }
    };


    template<typename T>
    size_t get_type_alignment() {
    struct aligner {
    char m_pad;
    T m_obj;
    };
    return offsetof(aligner, m_obj);
    }


    int main() {
    std::printf("%lu\n", (unsigned long)get_type_alignment<Foo>());


    //--------------------------------------------------------------
    std::puts("\n\n\n____________________________________________"
    "____\npress <ENTER> to exit...");
    std::fflush(stdin);
    std::fflush(stdout);
    std::getchar();
    return 0;
    }
    ___________________________________________________________________




    Also, perhaps the following code will help you:

    http://groups.google.com/group/comp.lang.c /browse_frm/thread/f62bd4db8de1aad2
    (read all...)
    Chris M. Thomasson, Feb 27, 2009
    #11
  12. This should do what you want:
    ____________________________________________________________________
    #include <cstddef>
    #include <cstdio>
    #include <new>


    struct Foo {
    int b;
    char a;
    double c;

    Foo(int b) {
    // [...];
    }
    };


    #define ALIGN_POW2(mp_this, mp_type) ((mp_type)( \
    (((std::ptrdiff_t)(mp_this)) + 1) & (-2) \
    ))


    #define ALIGN(mp_this, mp_type, mp_align) ((mp_type)( \
    (((std::ptrdiff_t)(mp_this)) + \
    ALIGN_POW2(mp_align, std::ptrdiff_t) - 1) \
    & (-ALIGN_POW2(mp_align, std::ptrdiff_t)) \
    ))


    template<typename T, std::size_t CUSTOM_ALIGN = 0>
    struct alignment {
    struct aligner {
    char m_pad;
    T m_obj;
    };

    enum constant {
    ALIGN_SIZE = (! CUSTOM_ALIGN) ? offsetof(aligner, m_obj) :
    CUSTOM_ALIGN
    };

    template<typename T1>
    static T1* align_ptr(void* ptr) {
    return ALIGN(ptr, T1, ALIGN_SIZE);
    }

    class buffer {
    enum constant {
    REAL_SIZE = sizeof(T) + ALIGN_SIZE - 1
    };

    unsigned char m_raw[REAL_SIZE];
    unsigned char* const m_align;

    public:
    buffer() : m_align(ALIGN(m_raw, unsigned char*, ALIGN_SIZE)) {
    std::printf("buffer size: %lu\n", (unsigned long)REAL_SIZE);
    std::printf("raw buffer: %p\n", (void*)m_raw);
    std::printf("align buffer: %p\n", (void*)m_align);
    }

    unsigned char* get() const {
    return m_align;
    }
    };
    };


    int main() {
    alignment<Foo>::buffer buffer1;

    Foo* foo = new (buffer1.get()) Foo(123);

    foo->~Foo();

    // 1024 byte buffer aligned on a 128 byte boundary...
    alignment<unsigned char[1024], 128>::buffer buffer2;


    //--------------------------------------------------------------
    std::puts("\n\n\n____________________________________________"
    "____\npress <ENTER> to exit...");
    std::fflush(stdin);
    std::fflush(stdout);
    std::getchar();
    return 0;
    }
    ____________________________________________________________________




    Any thoughts?
    Chris M. Thomasson, Feb 27, 2009
    #12
  13. James Kanze Guest

    On Feb 26, 7:57 pm, peter koch <> wrote:
    > On 26 Feb., 19:36, wrote:


    [...]
    > > To force the unsigned char array to have the same alignment
    > > as the Foo (which is my goal), I'd like to put these
    > > together in a union. However, Foo has a non-trivial
    > > constructor, so it may not be a member of a union. Do I have
    > > any othre options?


    > Yes. Search this group and the moderated one for a solution
    > that will give the correct alignment (basically: a union
    > containing all possible types and the char representation).


    I'm pretty sure you know this, but for precision's sake: the set
    of all possible types is infinite, which means that you're going
    to have to compromize some. Generally speaking, the set of all
    basic types, plus a couple of different types of pointers
    (void*, int*, struct X*, a pointer to a function, maybe pointers
    to different types of members) should largely suffice. (It
    would fail, of course, if in the implementation, the size of a
    pointer depends on a hash code of the canonical type of the
    pointed to object. Which is, I think, legal, but not something
    I'd worry about encountering. It might change if the compiler
    ensures some sort of special alignment for arrays, in order to
    use some special hardware.)

    In practice, this may result in a larger array than necessary if
    the other type is small, e.g.:

    struct Foo { char a[2] ; } ;

    union {
    unsigned char data[ sizeof( Foo ) ] ;
    MaxAlignment dummyForAlignment ;
    } ;

    (where MaxAlignment is a union of all of the types). To avoid
    this, you can do something like:

    template< typename T, bool isSmaller >
    struct AlignTypeDetail ;

    template< typename T >
    struct AlignTypeDetail< T, false >
    {
    typedef T type ;
    } ;

    template< typename T >
    struct AlignTypeDetail< T, true >
    {
    typedef char type ;
    } ;

    template< typename T, typename U >
    struct AlignType
    {
    typedef typename AlignTypeDetail< U, (sizeof( T ) < sizeof
    ( U )) >::type
    type ;
    } ;

    template< typename T >
    union MaxAlignFor
    {
    typename AlignType< T, char >::type c ;
    typename AlignType< T, short >::type s ;
    typename AlignType< T, int >::type i ;
    typename AlignType< T, long >::type l ;
    typename AlignType< T, long long >::type ll ;
    typename AlignType< T, float >::type f ;
    typename AlignType< T, double >::type d ;
    typename AlignType< T, long double >::type ld ;
    typename AlignType< T, void* >::type pc ;
    typename AlignType< T, MaxAlign* >::type ps ;
    typename AlignType< T, void (*)() >::type pf ;
    // (I've yet to find a machine where I've needed
    // more than the above.)
    } ;

    Since the required alignment for Foo can never be more than
    sizeof(Foo), this only puts types whose size is less than or
    equal to the size of Foo in the union.

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
    James Kanze, Mar 2, 2009
    #13
  14. James Kanze Guest

    On Feb 27, 4:15 am, "Chris M. Thomasson" <> wrote:
    > <> wrote in message


    > news:...


    > > Please consider the two definitions below:


    > > Foo foo;
    > > unsigned char foo[sizeof(Foo)];


    > > Are these guaranteed to have the same alignment, or will the
    > > second definition have an alignment that is only modulo 1?


    > You can attempt to calculate alignment of `Foo' objects like this:


    Which isn't what he needs, but...
    > ___________________________________________________________________
    > #include <cstddef>
    > #include <cstdio>


    > struct Foo {
    > char a;
    > int b;
    > double c;


    > Foo(int b) {
    > // [...];
    > }
    > };


    > template<typename T>
    > size_t get_type_alignment() {
    > struct aligner {
    > char m_pad;
    > T m_obj;
    > };
    > return offsetof(aligner, m_obj);


    This is undefined behavior if T isn't a POD (and Foo isn't). It
    won't compile with at least one compiler I use.

    > }


    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
    James Kanze, Mar 2, 2009
    #14
  15. "James Kanze" <> wrote in message
    news:...
    On Feb 27, 4:15 am, "Chris M. Thomasson" <> wrote:
    > <> wrote in message


    > > news:...


    > > > Please consider the two definitions below:


    > > > Foo foo;
    > > > unsigned char foo[sizeof(Foo)];


    > > > Are these guaranteed to have the same alignment, or will the
    > > > second definition have an alignment that is only modulo 1?


    > > You can attempt to calculate alignment of `Foo' objects like this:


    > Which isn't what he needs, but...


    > > ___________________________________________________________________
    > > #include <cstddef>
    > > #include <cstdio>


    > > struct Foo {
    > > char a;
    > > int b;
    > > double c;


    > > Foo(int b) {
    > > // [...];
    > > }
    > > };


    > > template<typename T>
    > > size_t get_type_alignment() {
    > > struct aligner {
    > > char m_pad;
    > > T m_obj;
    > > };
    > > return offsetof(aligner, m_obj);


    > This is undefined behavior if T isn't a POD (and Foo isn't). It
    > won't compile with at least one compiler I use.


    DOH!!! Yes, of course! My mistake. Thanks!

    > > }





    What about something like the following hack James?:
    ______________________________________________________________________
    #include <cstddef>
    #include <cstdio>
    #include <climits>
    #include <new>




    template<typename T, std::size_t CUSTOM_ALIGN = 0U>
    class alignment {
    struct aligner_1 {
    T m_obj;
    };

    struct aligner_2 {
    char m_pad;
    aligner_1 m_obj;
    };


    public:
    enum constant {
    ALIGN_SIZE = (! CUSTOM_ALIGN)
    ? sizeof(aligner_2) - sizeof(aligner_1)
    : CUSTOM_ALIGN,
    BUFFER_SIZE = sizeof(aligner_1) + (size_t)ALIGN_SIZE - 1U
    };

    static void* align_ptr(void* ptr) {
    return ALIGN_SIZE > 1
    ? (void*)((((size_t)ptr) + ((size_t)ALIGN_SIZE - 1U))
    & ~((size_t)ALIGN_SIZE - 1U))
    : ptr;
    }


    private:
    typedef char sassert[
    ALIGN_SIZE > 0 &&
    BUFFER_SIZE > 0 &&
    ALIGN_SIZE <= INT_MAX &&
    BUFFER_SIZE <= INT_MAX &&
    ALIGN_SIZE > 1 ? ! ((size_t)ALIGN_SIZE % 2U) : 1 &&
    sizeof(std::size_t) == sizeof(void*) ? 1 : -1
    ];
    };




    struct Base {
    char x;
    virtual void foo() = 0;
    };


    struct Foo : Base {
    char a[5];
    int b[3];
    double c[2];

    Foo(int x) {
    // [...];
    }

    void foo() {

    }
    };




    int main() {
    std::printf(
    "alignment of Foo: %lu\n"
    "alignment of Foo*: %lu\n"
    "alignment of Foo&: %lu\n",
    (unsigned long)alignment<Foo>::ALIGN_SIZE,
    (unsigned long)alignment<Foo*>::ALIGN_SIZE,
    (unsigned long)alignment<Foo&>::ALIGN_SIZE
    );

    unsigned char foo_raw_buffer[
    alignment<Foo>::BUFFER_SIZE
    ];

    Foo* f = new (alignment<Foo>::align_ptr(foo_raw_buffer)) Foo(123);

    std::printf(
    "\nfoo_raw_buffer: %p\n"
    "foo_raw_buffer_size: %lu\n"
    "foo_align_buffer: %p\n",
    (void*)foo_raw_buffer,
    (unsigned long)alignment<Foo>::BUFFER_SIZE,
    (void*)f
    );

    f->~Foo();

    unsigned char page_raw_buffer[
    alignment<unsigned char[8192], 8192>::BUFFER_SIZE
    ];

    void* page_align_buffer =
    alignment<unsigned char[8192], 8192>::align_ptr(page_raw_buffer);

    std::printf(
    "\npage_raw_buffer: %p\n"
    "page_raw_buffer_size: %lu\n"
    "page_align_buffer: %p\n",
    (void*)page_raw_buffer,
    (unsigned long)alignment<unsigned char[8192], 8192>::BUFFER_SIZE,
    page_align_buffer
    );

    std::printf(
    "\nalignment of char: %lu\n"
    "alignment of short: %lu\n"
    "alignment of int: %lu\n"
    "alignment of long: %lu\n"
    "alignment of float: %lu\n"
    "alignment of double: %lu\n",
    (unsigned long)alignment<char>::ALIGN_SIZE,
    (unsigned long)alignment<short>::ALIGN_SIZE,
    (unsigned long)alignment<int>::ALIGN_SIZE,
    (unsigned long)alignment<long>::ALIGN_SIZE,
    (unsigned long)alignment<float>::ALIGN_SIZE,
    (unsigned long)alignment<double>::ALIGN_SIZE
    );




    //--------------------------------------------------------------
    std::puts("\n\n\n____________________________________________"
    "____\npress <ENTER> to exit...");
    std::fflush(stdin);
    std::fflush(stdout);
    std::getchar();
    return 0;
    }
    ______________________________________________________________________




    Does that compile on all your compilers? Odd that the broken code which used
    `offsetof' macro on non-POD type compiles file on Comeau without warning. Oh
    well, shi% happens.


    How can I improve this hack?



    ;^(...
    Chris M. Thomasson, Mar 2, 2009
    #15
  16. "blargg" <> wrote in message
    news:blargg.ei3-0103091103350001@192.168.1.4...
    > Chris M. Thomasson wrote:
    >> [...]


    You make good points blargg. The hack was busted.


    > [...]
    > Perhaps you could eliminate this by using the size of aligner less the
    > size of T. Putting it all together into a simplified class:
    >
    > #include <iostream>
    > #include <cstddef>
    > using namespace std;
    >
    > template<typename T>
    > class alignment {
    > struct align_t {
    > char pad;
    > T obj;
    > };
    > public:
    > // Alignment requirement of T
    > enum { n = sizeof (align_t) - sizeof (T) };
    >
    > // Size of buffer needed when its alignment is unknown
    > enum { buf = sizeof (align_t) - 1 };
    > };


    Well, what if T is a reference type? Should that not be something like:



    template<typename T>
    class alignment {
    struct align_1_t {
    T obj;
    };

    struct align_2_t {
    char pad;
    align_1_t obj;
    };

    public:
    // Alignment requirement of T
    enum { n = sizeof (align_2_t) - sizeof (align_1_t) };

    // Size of buffer needed when its alignment is unknown
    enum { buf = sizeof (align_1_t) + n - 1 };
    };



    What am I missing here?
    Chris M. Thomasson, Mar 2, 2009
    #16
  17. James Kanze Guest

    On Mar 2, 4:13 pm, "Chris M. Thomasson" <> wrote:
    > "James Kanze" <> wrote in message


    > news:...
    > On Feb 27, 4:15 am, "Chris M. Thomasson" <>
    > wrote:


    > > <> wrote in message
    > > >news:....
    > > > > Please consider the two definitions below:
    > > > > Foo foo;
    > > > > unsigned char foo[sizeof(Foo)];
    > > > > Are these guaranteed to have the same alignment, or will the
    > > > > second definition have an alignment that is only modulo 1?
    > > > You can attempt to calculate alignment of `Foo' objects like this:

    > > Which isn't what he needs, but...
    > > > ___________________________________________________________________
    > > > #include <cstddef>
    > > > #include <cstdio>
    > > > struct Foo {
    > > > char a;
    > > > int b;
    > > > double c;
    > > > Foo(int b) {
    > > > // [...];
    > > > }
    > > > };
    > > > template<typename T>
    > > > size_t get_type_alignment() {
    > > > struct aligner {
    > > > char m_pad;
    > > > T m_obj;
    > > > };
    > > > return offsetof(aligner, m_obj);

    > > This is undefined behavior if T isn't a POD (and Foo isn't). It
    > > won't compile with at least one compiler I use.


    > DOH!!! Yes, of course! My mistake. Thanks!


    > > > }


    > What about something like the following hack James?:
    > ______________________________________________________________________
    > #include <cstddef>
    > #include <cstdio>
    > #include <climits>
    > #include <new>


    > template<typename T, std::size_t CUSTOM_ALIGN = 0U>
    > class alignment {
    > struct aligner_1 {
    > T m_obj;
    > };


    > struct aligner_2 {
    > char m_pad;
    > aligner_1 m_obj;
    > };


    > public:
    > enum constant {
    > ALIGN_SIZE = (! CUSTOM_ALIGN)
    > ? sizeof(aligner_2) - sizeof(aligner_1)
    > : CUSTOM_ALIGN,
    > BUFFER_SIZE = sizeof(aligner_1) + (size_t)ALIGN_SIZE - 1U
    > };


    > static void* align_ptr(void* ptr) {
    > return ALIGN_SIZE > 1
    > ? (void*)((((size_t)ptr) + ((size_t)ALIGN_SIZE - 1U))
    > & ~((size_t)ALIGN_SIZE - 1U))
    > : ptr;
    > }


    > private:
    > typedef char sassert[
    > ALIGN_SIZE > 0 &&
    > BUFFER_SIZE > 0 &&
    > ALIGN_SIZE <= INT_MAX &&
    > BUFFER_SIZE <= INT_MAX &&
    > ALIGN_SIZE > 1 ? ! ((size_t)ALIGN_SIZE % 2U) : 1 &&
    > sizeof(std::size_t) == sizeof(void*) ? 1 : -1
    > ];
    > };


    My basic question is why? It doesn't enforce the alignment of
    the buffer; it allocates a slightly larger buffer, and then
    determines the first aligned address in it. A solution using a
    union will force the compiler to align correctly to begin with.

    [...]
    > Does that compile on all your compilers?


    Probably.

    > Odd that the broken code which used `offsetof' macro on
    > non-POD type compiles file on Comeau without warning.


    It's more or less a library issue. G++ can detect the problem
    because offsetof is defined as something like:
    #define offsetof( a, b ) __buildin_offsetof( a, b )
    and handled by the compiler. The library you're using with
    Comeau probably exploits some other undefined behavior; the
    classical implementation is something like:
    #define offsetof( a, b ) ((size_t)(&((a*)0)->b))
    This dereferences a null pointer, but in a way such that most
    compilers won't actually generate any code for it. So it never
    causes a compiler error, nor a core dump (but in some cases
    where virtual bases are involved, it might give a wrong answer).

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
    James Kanze, Mar 3, 2009
    #17
  18. "James Kanze" <> wrote in message
    news:...
    On Mar 2, 4:13 pm, "Chris M. Thomasson" <> wrote:
    > [...]
    > What about something like the following hack James?:
    > ______________________________________________________________________
    > > [...]


    > My basic question is why? It doesn't enforce the alignment of
    > the buffer; it allocates a slightly larger buffer, and then
    > determines the first aligned address in it. A solution using a
    > union will force the compiler to align correctly to begin with.


    How can I use a union to align an arbitrary object up to, say, a 8192 byte
    boundary? I can do this using the posted hack like:
    _______________________________________________________________________
    void foo() {
    unsigned char page_raw_buffer[
    alignment<unsigned char[8192], 8192>::BUFFER_SIZE
    ];

    void* page_align_buffer =
    alignment<unsigned char[8192], 8192>::align_ptr(page_raw_buffer);
    }
    _______________________________________________________________________




    What am I missing?
    Chris M. Thomasson, Mar 7, 2009
    #18
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. =?Utf-8?B?bWFudQ==?=

    Regd---Justify option in Alignment.

    =?Utf-8?B?bWFudQ==?=, Sep 23, 2005, in forum: ASP .Net
    Replies:
    0
    Views:
    434
    =?Utf-8?B?bWFudQ==?=
    Sep 23, 2005
  2. ALuPin

    Phase alignment

    ALuPin, May 17, 2004, in forum: VHDL
    Replies:
    0
    Views:
    572
    ALuPin
    May 17, 2004
  3. Sunil Menon

    Re: Help required for alignment problem

    Sunil Menon, Jun 26, 2003, in forum: ASP .Net
    Replies:
    0
    Views:
    803
    Sunil Menon
    Jun 26, 2003
  4. Anne
    Replies:
    0
    Views:
    638
  5. Anne
    Replies:
    0
    Views:
    517
Loading...

Share This Page