[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: problem with string.format %d and very large integers
- From: Lorenzo Donati <lorenzodonatibz@...>
- Date: Fri, 29 Jul 2011 13:47:18 +0200
On 27/07/2011 23.10, Luiz Henrique de Figueiredo wrote:
> =big
2500000000
> =string.format('%d', big)
-2147483648
This works fine in 5.2:
Lua 5.2.0 Copyright (C) 1994-2011 Lua.org, PUC-Rio
big=2500000000
=string.format('%d', big)
2500000000
Now this is interesting: I tried to understand lstrlib.c and the code of
str_format. I added some debug prints in the case branch for "%d":
---------------------------------------------------------------------
case 'd': case 'i':
case 'o': case 'u': case 'x': case 'X': {
lua_Number n = luaL_checknumber(L, arg);
/* DEBUG */
printf("long long width: %d bit\n", sizeof(long long) * CHAR_BIT );
long long nnn = 2LL << 30; /* 2^31 */
double ddd = nnn;
nnn = ddd; /* check round-trip */
printf( "ddd = %.0f\n", ddd );
printf( "nnn = %lld\n", nnn );
/* END DEBUG */
LUA_INTFRM_T r = (n < 0) ? (LUA_INTFRM_T)n :
(LUA_INTFRM_T)(unsigned LUA_INTFRM_T)n;
addlenmod(form, LUA_INTFRMLEN);
nb = sprintf(buff, form, r);
break;
---------------------------------------------------------------------
When executing this lua code with the "hacked" interpreter:
x = 2^31; print( ("%.0f %d"):format(x,x) )
it outputs:
long long width: 64 bit
ddd = 2147483648
nnn = -2147483648
2147483648 -2147483648
so it would seem that %lld conversion support in printf is broken.
But then I created a simple test.c file with the same debug prints:
---------------------------------------------------------------------
#include <stdio.h>
#include <limits.h>
int main()
{
printf("long long width: %d bit\n", sizeof(long long) * CHAR_BIT );
long long nnn = 2LL << 30; /* 2^31 */
double ddd = nnn;
nnn = ddd; /* check round-trip */
printf( "ddd = %.0f\n", ddd );
printf( "nnn = %lld\n", nnn );
}
---------------------------------------------------------------------
And compiled it this way:
gcc test.c -c -O2 -Wall -pedantic -std=c90
gcc test.o -o test.exe -O2 -Wall -pedantic -std=c90
Besides some warnings about C90 not supporting "long long ints", all
went ok, and when running test.exe it gives:u
long long width: 64 bit
ddd = 2147483648
nnn = 2147483648
I works!
So there must be some strange combination of compiler flags in the
standard makefile that makes GCC do the wrong thing for %lld in printf.
I also checked with DependencyWalker that test.exe uses the same runtime
(only msvcrt.dll). So it seems that it isn't msvcrt's fault either.
So now I'm completely puzzled, and I reached the limits of my C hacking
ability. :-(
-- Lorenzo