Re: Alignment
"James Kanze" <james.kanze@gmail.com> wrote in message
news:891084b3-ce7d-4a9a-b893-14499e22a2bc@j35g2000yqh.googlegroups.com...
On Feb 27, 4:15 am, "Chris M. Thomasson" <n...@spam.invalid> wrote:
<better_cs_...@yahoo.com> wrote in message
news:eab8ea3f-5616-4fd8-b2b0-16f86fe0b7a8@q1g2000vbn.googlegroups.com...
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?
;^(...