lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


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