X
xmllmx
Please forgive me for cross-posting. I've post this to
microsoft.publoc.vc.mfc. But I can't get any response. Maybe only MFC-
related topics are cared there.
To begin with code:
union XXX
{
double a;
char b;
double c;
};
XXX s;
size_t n1 = sizeof(XXX);
size_t n2 = __alignof(double);
size_t n3 = __alignof(XXX);
double* p1 = &s.a;
char* p2 = &s.b;
double* p3 = &s.c;
XXX* p4 = &s;
Compiler: VS 2005 + SP1
Output:
n1 = 8
n2 = 8 // the largest member in the union is 8-byte aligned!
n3 = 4 // ???, it should be 4 less than 8
p1 = 0x0012F5B4 // ???, it is not 8-byte aligned!
p2 = 0x0012F5B4 // ditto
p3 = 0x0012F5B4 // ditto
p4 = 0x0012F5B4 // ditto
Below is a related article copied from the site "The Old New Thing".
Because posting new comments to the original post has been disabled,
so I have to put it here. Please note the first comments to the post
by Roger Lipscombe, He/She says: "the C standard states that they must
be aligned suitably for the largest contained member." However, I
can't find any statement in the C standard, Is that implementation-
defined?
Thanks in advance!
================ Quotation ======================
The original link: http://blogs.msdn.com/oldnewthing/archive/2004/08/25/220195.aspx
Why can't you treat a FILETIME as an __int64?
The FILETIME structure represents a 64-bit value in two parts:
typedef struct _FILETIME {
DWORD dwLowDateTime;
DWORD dwHighDateTime;
} FILETIME, *PFILETIME;
You may be tempted to take the entire FILETIME structure and access it
directly as if it were an __int64. After all, its memory layout
exactly matches that of a 64-bit (little-endian) integer. Some people
have written sample code that does exactly this:
pi = (__int64*)&ft; // WRONG
(*pi) += (__int64)num*datepart; // WRONG
Why is this wrong?
Alignment.
Since a FILETIME is a structure containing two DWORDs, it requires
only 4-byte alignment, since that is sufficient to put each DWORD on a
valid DWORD boundary. There is no need for the first DWORD to reside
on an 8-byte boundary. And in fact, you've probably already used a
structure where it doesn't: The WIN32_FIND_DATA structure.
typedef struct _WIN32_FIND_DATA {
DWORD dwFileAttributes;
FILETIME ftCreationTime;
FILETIME ftLastAccessTime;
FILETIME ftLastWriteTime;
DWORD nFileSizeHigh;
DWORD nFileSizeLow;
DWORD dwReserved0;
DWORD dwReserved1;
TCHAR cFileName[ MAX_PATH ];
TCHAR cAlternateFileName[ 14 ];
} WIN32_FIND_DATA, *PWIN32_FIND_DATA, *LPWIN32_FIND_DATA;
Observe that the three FILETIME structures appear at offsets 4, 12,
and 20 from the beginning of the structure. They have been thrown off
8-byte alignment by the dwFileAttributes member.
Casting a FILETIME to an __int64 therefore can (and in the
WIN32_FIND_DATA case, will) create a misaligned pointer. Accessing a
misaligned pointer will raise a STATUS_DATATYPE_MISALIGNMENT exception
on architectures which require alignment.
Even if you are on a forgiving platform that performs automatic
alignment fixups, you can still run into trouble. More on this and
other consequences of alignment in the next few entries.
Exercise: Why are the LARGE_INTEGER and ULARGE_INTEGER structures not
affected?
===================================
Comments by Roger Lipscombe
LARGE_INTEGER and ULARGE_INTEGER are unions, and the C standard states
that they must be aligned suitably for the largest contained member --
which is a LONLONG or ULONGLONG, respectively.
microsoft.publoc.vc.mfc. But I can't get any response. Maybe only MFC-
related topics are cared there.
To begin with code:
union XXX
{
double a;
char b;
double c;
};
XXX s;
size_t n1 = sizeof(XXX);
size_t n2 = __alignof(double);
size_t n3 = __alignof(XXX);
double* p1 = &s.a;
char* p2 = &s.b;
double* p3 = &s.c;
XXX* p4 = &s;
Compiler: VS 2005 + SP1
Output:
n1 = 8
n2 = 8 // the largest member in the union is 8-byte aligned!
n3 = 4 // ???, it should be 4 less than 8
p1 = 0x0012F5B4 // ???, it is not 8-byte aligned!
p2 = 0x0012F5B4 // ditto
p3 = 0x0012F5B4 // ditto
p4 = 0x0012F5B4 // ditto
Below is a related article copied from the site "The Old New Thing".
Because posting new comments to the original post has been disabled,
so I have to put it here. Please note the first comments to the post
by Roger Lipscombe, He/She says: "the C standard states that they must
be aligned suitably for the largest contained member." However, I
can't find any statement in the C standard, Is that implementation-
defined?
Thanks in advance!
================ Quotation ======================
The original link: http://blogs.msdn.com/oldnewthing/archive/2004/08/25/220195.aspx
Why can't you treat a FILETIME as an __int64?
The FILETIME structure represents a 64-bit value in two parts:
typedef struct _FILETIME {
DWORD dwLowDateTime;
DWORD dwHighDateTime;
} FILETIME, *PFILETIME;
You may be tempted to take the entire FILETIME structure and access it
directly as if it were an __int64. After all, its memory layout
exactly matches that of a 64-bit (little-endian) integer. Some people
have written sample code that does exactly this:
pi = (__int64*)&ft; // WRONG
(*pi) += (__int64)num*datepart; // WRONG
Why is this wrong?
Alignment.
Since a FILETIME is a structure containing two DWORDs, it requires
only 4-byte alignment, since that is sufficient to put each DWORD on a
valid DWORD boundary. There is no need for the first DWORD to reside
on an 8-byte boundary. And in fact, you've probably already used a
structure where it doesn't: The WIN32_FIND_DATA structure.
typedef struct _WIN32_FIND_DATA {
DWORD dwFileAttributes;
FILETIME ftCreationTime;
FILETIME ftLastAccessTime;
FILETIME ftLastWriteTime;
DWORD nFileSizeHigh;
DWORD nFileSizeLow;
DWORD dwReserved0;
DWORD dwReserved1;
TCHAR cFileName[ MAX_PATH ];
TCHAR cAlternateFileName[ 14 ];
} WIN32_FIND_DATA, *PWIN32_FIND_DATA, *LPWIN32_FIND_DATA;
Observe that the three FILETIME structures appear at offsets 4, 12,
and 20 from the beginning of the structure. They have been thrown off
8-byte alignment by the dwFileAttributes member.
Casting a FILETIME to an __int64 therefore can (and in the
WIN32_FIND_DATA case, will) create a misaligned pointer. Accessing a
misaligned pointer will raise a STATUS_DATATYPE_MISALIGNMENT exception
on architectures which require alignment.
Even if you are on a forgiving platform that performs automatic
alignment fixups, you can still run into trouble. More on this and
other consequences of alignment in the next few entries.
Exercise: Why are the LARGE_INTEGER and ULARGE_INTEGER structures not
affected?
===================================
Comments by Roger Lipscombe
LARGE_INTEGER and ULARGE_INTEGER are unions, and the C standard states
that they must be aligned suitably for the largest contained member --
which is a LONLONG or ULONGLONG, respectively.