P64 Gotcha List
----------------
1. sizeof long array can overflow on lp64.
uchar n = sizeof( 50*sizeof(long)); // 200 bytes in ilp32, 400 bytes in lp64.
2. Use u U L l suffix on large const.
long l = 1 <<32; // 0 on ilp32,lp64
long l = 1L<<32; // 2^32 on lp64, 0 on ilp32.
Solaris: see /usr/include/sys/inttypes.h
INT64_C(5) => 5ll for ILP32, and 5l for LP64.
0x80000000L ulong in lp32, long in lp64.
3. Bit fields are converted to int and sign-extended (or uint if too large) in expr.
struct { uint b:19, r:13 }x;
uint y = x.b<<13 // x.b first converted to int and sign extended!
uint y = (uint)x.b << 13; // ok.
4. Integer Arithmetic on ptr, ptr is trucated to int32.
char *p="x";
(int)p+1=='\0' // p is trunc to int32.
(uintptr_t)p+1=='\0' // ok.
5. Unprototyped func returning ptr is trucated to int32.
// int login(...); -- implicit C decl.
char *p = getenv("HOME"); // p is trucated to int32, crash.
6. Saving ptr in int, losses upper 4 bytes of ptr.
void *q;
int p = (int)q; // truncated to int32
7. Unions with long.
union {
long x;
int y; // on lp64, y gets lsb of x.
}
8. Print format specifier
char *p="x";
printf("p=0x%08x",p); // losses msb.
printf("p=%p", p); // ok.
long x=LONG_MAX;
printf("x=%d ",x); // truncated, wrong.
printf("x=%ld",x); // ok.
9. Casting *int into *long.
int *i;
long *p;
p+1; // p+=4 on ilp32
p+1; // p+=8 on lp64
p = (long*) i; // p misaligned pointing to *i and *(i+1).
i = ( int*) p; // i pointing to lsb of p.
10. Unsigned bit fields (default sign and alignment).
struct { b:12, int:0, d:5 } x; // b is unsigned in lp64, signed
in ilp32.
// :0 affects alignment in ilp32, no effect in lp64.
11. LP64 Perf Problems
Larger exe, need more TLB, cache, mem (wrt same src compiled as ILP32).
Long div slow in lp64, eg. 1L/9.
Int Array indexes are sign-ext on every use, need more instruction in LP64, eg. int i; a[i];
12. Expression sizing:
Example.
int x,y;
long z = x + y; // x+y done in 32bit, then assignment will resize result for z.
Example.
ulong y = (1 <<32); // overflows in lp32 and lp64.
ulong y = (1L<<32); // overflows in lp32, ok 2^32 in lp64.
13. Promotions:
result = a op b;
// 1. type of tmp is of max of a and b.
// 2. tmp = a op b
// 3. promote tmp to type of result, ptmp.
// 4. result = ptmp;
Example.
long l=-1; uint i=1;
if( l > i ) printf("ilp32"); // -1 is promoted to uint32.
else printf("lp64"); // both promoted to signed 64.
if( l > (long)i ) // fix
...;
Example.
main(){ // k is -1 in LP32, 4294967295 in LP64
int i = -2;
unsigned int j = 1;
long k = i+j;
printf("int %d+ uint %ld= long k is %ld\n",i,j,k);
}
15. Prototype:
// #include <stdlib.h> missing.
int *i = malloc(sizeof(*i));
// Ok in lp32, Crash on lp64 because
// malloc will return 32bit int value because of missing prototype.
}
////////////////////////////////////////////////////
Examples
> cc +DA2.0W +w1 +M2 enquire.c # +w1 for warnings, +M2 for 64bits
long double=128 bits
# Sort LP64 warning by problem:
> make 2>&1 | grep LP64 | xsort 'warning:\s+\S+:' | align warn > lp64.log
> vim lp64.log
:set isk+=46 " Make . part of tag, so file.c is a keyword for tags"
> emacs lp64.log
> M-x compilation-minor-mode
> M-x next-error
; if cant find files, set
; (setq compilation-search-path '("dir1" "dir2")) C-xC-e
/714: Function "malloc" called with no prototype or definition in scope
/724: Initialization converts default int return type to pointer
/722:.*cast converts 32 bit constant to pointer
/725:.*cast converts 32 bit integer to pointer
/727:.*cast truncates pointer into 32 bit integer
/729:.*converts int* to long*
/732:.*different types treated as unsigned
/740:.*casting to a smaller size may truncate
/530:.*casting from loose to strict alignment
/720:.*Assignment may overflow
// Example
> catt -n x.c
1 void main(){
2 int *x, *q, i;
3 long l=-1;
4 x = malloc(sizeof(int)*10);
5 (int*)i;
6 (int) &i;
7 (long*)&i;
8 i = l;
9 }
hp64> cc +DA2.0W +M2 +w1 -Aa x.c
/*
line 4: warning 714: Function "malloc" called with no prototype or definition in scope.
line 4: warning 724: LP64 migration: Assignment converts default int return type to pointer "x".
line 5: warning 725: LP64 migration: Cast converts 32 bit integer to pointer.
line 6: warning 727: LP64 migration: Cast truncates pointer into 32 bit integer.
line 7: warning 530: LP64 migration: Casting from loose to strict alignment: Resulting pointer may be misaligned.
line 7: warning 729: LP64 migration: Cast converts int* to long*.
line 8: warning 720: LP64 migration: Assignment may overflow integer "i".
*/
/////////////////////////////////////////////////
A. Sizes
Ansi sizeof() is always unsigned, try:
if( 0-sizeof(int) > 0 ) printf("See: 0-sizeof(int) is unsigned!\n");
ILP32: win32 hp11 solaris linux
ANSI C Integer Requirements, see C book. moshtag=ansi_int
sizeof(int) >= sizeof(short) >= 2.
sizeof(long) >=sizeof(int)
sizeof(long) >= 4.
LP64: hp11_64 solaris_64 (assume default for 64bit).
New: sizeof(long)==sizeof(void*)==8, rest unchanged.
P64: win64
New: sizeof(void*)==8, rest unchanged.
//////////////////////////////////////////////////////////
Linux64 moshtag=linux64
char = 8 bits, signed
short=16 int=32 long=64 float=32 double=64 bits
long double=128 bits
Type size_t is unsigned long
ALIGNMENTS
char=1 short=2 int=4 long=8 float=4 double=8 long double=16
char*=8 int*=8 func*=8
short: BA
int: DCBA
long: HGFEDCBA
Maximum long = 9223372036854775807 (= 2**63-1)
Minimum long = -9223372036854775808
Maximum unsigned short = 65535
Maximum unsigned int = 4294967295
Maximum unsigned long = 18446744073709551615
PROMOTIONS
unsigned short promotes to signed int
long+unsigned gives signed long
HP64 ALIGNMENTS
char=1 short=2 int=4 long=8 float=4 double=8 long double=16
char*=8 int*=8 func*=8
1 Comments:
How would you display the pointer data in Hex? For example,
long n = LONG_MAX;
printf("%08x \n",n);
It says format ‘%08x’ expects type ‘unsigned int’, but argument 3 has type.
If I have unsigned short * pointer, I want to use this with void * pointer,
short *ptr;
void *aligned_ptr;
ptr = (short *)aligned_ptr;
In this case, I want to store 16-bit register value in that pointer.
Could you please give me some solution?
Post a Comment
<< Home