[th/gcc4] apps fixing guide #2 - aliasing violations.

Grzegorz Konopko kolodko1 w wp.pl
Pią, 5 Maj 2006, 16:36:49 CEST


Dnia czwartek, 4 maja 2006 22:34, Grzegorz Konopko napisał:
> Dnia czwartek, 4 maja 2006 20:22, Paweł Sikora napisał:
> > [3] OK.
> > tutaj nadal jest poprawnie, bo typ znakowy może się nakładać na inne
> > typy.
> >
> > bool tell_endian()
> > {
> >         unsigned x = 1;
> >         return *(char*)&x;
> > }
> >
> > jednak dobrą praktyką jest unikać rzutowania przez wskaźniki
> > i zapisać powyższy przykład z użyciem unii -> [4].
>
> W powyższym chodzi o przejrzystość kodu?
>
> ze 2 tygodnie temu naciąłem sie na podobny własny trick, uzywam takich duzo
> bo czasem trzeba.
> Ale nie rozumiem dlaczego właściwie tak to tłumaczą,
To było głupie pytanie. To przecież Ansi/ISO.


Cieakwy przykład wyciagnelem z jednego tutoriala do srodowiska 
programistycznego.

/************************************************************************/
short f(short *sptr, long *lptr)
{
        short x = *sptr;
        *lptr = 0;
        return *sptr + x;

}

short fail()
{
        union
        {
                short s[2];
                long l;
        } u;
        u.s[0] = 4711;
        return f(&u.s[0], &u.l);
}

int main ()
{
        printf("%d\n",fail());

        return 0;
}
/************************************************************************/

i komentarz:

Because the *lptr = 0 assignment cannot affect the object sptr points to, the 
optimizer will assume that *sptr in the return statement has the same value 
as variable x was assigned at the beginning of the function. Hence, it is 
possible to eliminate a memory access by returning x << 1 instead of *sptr + 
x.


Co ciekawe na gcc zz Ac i gcc z th przy -O2 daje wynik 9422, przy wszystkich 
innych nawet -O3 daje 4711. Nie wiem czemu przy -O3 daje 4711(?).

Dodam jeszcze jeden fragment do tego co napisane w podreczniku gcc wziete z 
tego samego źródła:

short s;
unsigned short us; 

long l;
unsigned long ul;

float f;

unsigned short *usptr;
char *cptr;

struct A 
{
	short s;
	float f; 
} a; 

void test(float *fptr, long *lptr)
{
		/* May affect: */
 *lptr = 0; 	/* l, ul */ 
 *fptr = 1.0; 	/* f, a */ 
 *usptr = 4711; /* s, us, a */ 
 *cptr = 17; 	/* s, us, l, ul, f, usptr, cptr, a */ 
}

Because an object shall only be accessed as its declared type (or a qualified 
version of its declared type, or a signed/unsigned type corresponding to its 
declared type) it is also assumed that the object that fptr points to will 
not be affected by an assignment to the object that lptr points to.


Więcej informacji o liście dyskusyjnej pld-devel-pl