تسجيل الدخول

مشاهدة النسخة كاملة : Question on strict-aliasing



C++ Programming
08-12-2009, 01:50 PM
Hi experts,

I meet a question about strict-aliasing problem when compiling a code using gcc. The problem is described below:


#include
#include

unsigned long queue[10];
int queue_len = 0;

int main()
{
unsigned long a = 0x00010002;
unsigned short* b = (unsigned long*)(void*)&a; // we need a "(void*)" here, because we want to skip the strict-aliasing rule check.

b[0] = 6;
b[1] = 5;

printf("hello world %x", (int)a); // 6 5
return 0;
}


When you compile the code using the option below:


gcc -O3 -Wall


The result of "a" would not be changed.

However, when you compile the code using the option below:


gcc -O3 -Wall -fno-strict-aliasing


The result of "a" is changed.

This behaviour can be explained in the aliasing rule of GCC standard. The intention of strict-aliasing rule is to prevent the case that a pointee is being pointed to by a pointer of different type (the so-called type-punning error). In the case above, the pointer type of "&a" is (long*) while it is being accessed by pointer of type (short*), the action that being taken in (short*) will not take effect to the original pointee. This is a kind of trap introduced in GCC.

So, up to now, we can still explain the behavior, however, for the case below:


#include
#include

typedef struct _MyStruct
{
unsigned short a;
unsigned short b;
}MyStruct;

typedef struct _MyStruct2
{
unsigned char a;
unsigned char b;
unsigned char c;
unsigned char d;
}MyStruct2;

int main()
{
MyStruct a = {0x0001, 0x0002};
MyStruct2* b = (MyStruct2*)(void*)&a;// = malloc(sizeof(unsigned short*));

b->a = 0;
b->b = 5;
b->c = 0;
b->d = 6;


printf("hello world %x %x\r\n", (int)a.a, (int)a.b); //<span class="code-comment">