[parisc-linux] gcc and ++
phi
phi@hpfrcu81.france.hp.com
Wed, 02 Oct 2002 09:30:03 +0200
Hi,
Working on an endian neutral file reader, I bumped into sometihng strange with
gcc.
basically I got to read a 32 unsigned int from a file that is mmap'ed, I have
a unsigned char * that is supposed to be at the unsigned int addr but possibly
unaligned.
I have a macro defined like this, then allowing the unsigned int getter from
file to expression.
#define get_4(p) ( ((uint32)(*p++)<<24)| \
((uint32)(*p++)<<16)| \
((uint32)(*p++)<<8 )| \
((uint32)(*p++)) )
It assume the given p is
unsigned char *p;
then produce an uint32 expression.
Now using this macro on hpux/hpc linux/i386 linux/hppa gives 3 different
result with the linux/hppa particularly wrong IMHO. I wonder if this funny
could endup in kernel bugs?
==============================================================
Here is my test prog, get2_4 is a workaround attempt...
typedef unsigned char uint8;
typedef unsigned int uint32;
#define get_4(p) ( ((uint32)(*p++)<<24)| \
((uint32)(*p++)<<16)| \
((uint32)(*p++)<<8 )| \
((uint32)(*p++)) )
#define get2_4(p) ( p+=4, ((uint32)(p[-4])<<24)| \
((uint32)(p[-3])<<16)| \
((uint32)(p[-2])<<8 )| \
((uint32)(p[-1])) )
main()
{ uint32 i;
uint8 *p;
p="abcd"; printf("p=%#x ",p);
i=get_4(p);
printf("i=%#x p=%#x\n",i,p);
p="abcd"; printf("p=%#x ",p);
i=get2_4(p);
printf("i=%#x p=%#x\n",i,p);
}
==============================================================
Results:
HPUX/HPC:
---------
$ ./c
p=0x40001028 i=0x61626364 p=0x4000102c
p=0x40001048 i=0x61626364 p=0x4000104c
In both case i is loaded with the integer "abcd" (as expected I would say) and
after the expression p is bumped by 4 that is for sure expected.
Note the bad const re-use, hpc use 2 different "abcd" one at 0x40001028 the
other at 0x40001048 (but that's not a problem, +Osomething would eventually
get it right)
LINUX/i386:
----------
(red-hat 6.2 then very old compiler, may be someone can try on a very last
gcc?)
$ ./c
p=0x8048500 i=0x61616161 p=0x8048504
p=0x8048500 i=0x61626364 p=0x8048504
Here get_4(p) don't compute the expression corectly IMHO, but yet purist will
claim that KnR sez that side effect expression can't rely on order of
evaluation (bad practice programing), yet I wonder how the parse tree look
like here.
So i is semi wrong/right and p is bumped by 4 after the expression that is
expected.
get2_4(p), got i computed correctly and p bumped by 4, this is the workaround
I would use for the time being.
LINUX/hppa:
-----------
GNU C version 3.0.2 (Debian)
hpfrcw12:/tmp# ./c
p=0x10734 i=0x61616161 p=0x10735
p=0x10734 i=0x61626364 p=0x10738
Here get_4(p) is plain dead, i isn't computed correctly but as before one can
argue it is ok, but the pointer bump is completly wrong, there are 4 ++, and
no matter how we order the expression, p must be bumped by 4 it is bumped by
1!!!
So beside the scholastic discusion about when ++ should occur, I fear a bug in
the compiler that may have ramification in our kernel?
What do you think?
=============================================================================
Challenge.
If someone can come with a better definition for get_4(p) i.e can force the ++
at correct place, I would grab, right now I use get2_4() that seems to be
portable.
Cheers,
Phi