From: "Juan Manuel Guerrero" Organization: Darmstadt University of Technology To: djgpp-workers AT delorie DOT com Date: Tue, 26 Nov 2002 21:42:29 +0100 Subject: Difficulty with long double X-mailer: Pegasus Mail for Windows (v2.54DE) Message-ID: <1FCB82C4018@HRZ1.hrz.tu-darmstadt.de> X-MailScanner: Found to be clean Reply-To: djgpp-workers AT delorie DOT com Please look at the following code snippet: #include int main(void) { long double a=1.0e309; struct IEEExp { unsigned manl:32; unsigned manh:32; unsigned exp :15; unsigned sign:1; } ip = *(struct IEEExp *)&a; printf("a=%Lg\n",a); return 0; } As can be seen, the variable long double a is initialised with a value greater than DBL_MAX=1.79769e+308. AFAIK, the variable a should be able to store values equal or smaller than LDBL_MAX=1.18973e+4932. If the above program is started the output generated will be: a=Inf IMHO, that is wrong. 1.0e309 <<< 1.18973e+4932. I have generated assembler code for the above snippet. It looks like: .file "a.c" .section .text LC0: .ascii "a=%Lg\12\0" .p2align 1 .globl _main _main: push ebp mov ebp, esp sub esp, 40 and esp, -16 mov eax, 0 sub esp, eax // Initialising variable long double a: mov DWORD PTR [ebp-24], 0 // mantissa low (32 bit): 0x00000000 mov DWORD PTR [ebp-20], -2147483648 // mantissa high (32 bit): 0x80000000 mov DWORD PTR [ebp-16], 32767 // sign: 0x0 and biased exponent (15 bit): 0x7FFF mov eax, DWORD PTR [ebp-24] mov DWORD PTR [ebp-40], eax mov eax, DWORD PTR [ebp-20] mov DWORD PTR [ebp-36], eax mov eax, DWORD PTR [ebp-16] mov DWORD PTR [ebp-32], eax push DWORD PTR [ebp-16] push DWORD PTR [ebp-20] push DWORD PTR [ebp-24] push OFFSET FLAT:LC0 call _printf add esp, 16 mov eax, 0 leave ret .ident "GCC: (GNU) 3.2" Of course, we are dealing with intel's 80-bit extended double format. Mantissa high and low result in 64-bit mantissa: 0x8000000000000000 == 1.0(decimal). That is ok. But exponent minus bias gives: 0x7FFF - 0x3FFF = 0x4000 == 16384(decimal) != 1026(decimal) as it should be. Please note: 10^309 == 2^1026 and 10^4932 == 2^16384. It seems to be that a value assignement greater than DBL_MAX to a long double variable produces an "exponent overflow" generating an infinity. All this only happens if the exponent is greater than 308. Something similar can be observed for small exponents. As soon as the exponent becomes smaller than -308 it value jumps to -4932 implying that the value of a long double variable becomes zero no matter what exponent value is taken from the range [-308, -4932]. In conclusion long double seems to behave like double. The above data can also be observed if the code is compiled and inspected with gdb. An inspection of the IEEExp bit field with gdb shows the same data than the one shown in the assembler code. I have noticed this while I was implementing hex float support (new conversion type specifier 'a' and 'A') to _doprnt() as imposed by C99. Am I missing something? Can someone explain to my, why long double variables are not initialised as I would expect or what am I doing wrong? I am using gcc 3.2, binutils 2.13 and CVS libc (2002-11-25). TIA, Guerrero, Juan Manuel