Re: 64bit format strings



   Hi!

On Thu, Jan 20, 2005 at 09:10:44PM +0100, Tim Janik wrote:
> On Tue, 18 Jan 2005, Stefan Westerfeld wrote:
> >On AMD64, I currently get quite some warnings when compiling BEAST code
> >that contains a printf (or g_print, g_strdup_printf or similar) which
> >prints a 64 bit integer. The reason is that the format specifier that
> >indicates that a guint64 value is to be printed is different on AMD64.
> >On AMD64 with gcc, glib-2.0 defines g(u)int64 as long values (not long
> >long values), thus the format specifier for printf should be "%ld" not
> >"%lld".
> >
> >Thus, for instance in the glib-2.0 source, there is:
> >
> >#define FORMAT64 "%" G_GINT64_FORMAT " %" G_GUINT64_FORMAT "\n"
> > string = g_strdup_printf (FORMAT64, gi64t1, gu64t1);
> > sscanf (string, FORMAT64, &gi64t2, &gu64t2);
> > g_free (string);
> > g_assert (gi64t1 == gi64t2);
> > g_assert (gu64t1 == gu64t2);
> >
> >in tests/type-test.c.
> >
> >Is it okay to start committing fixes to the BEAST CVS for this, which
> >would for instance fix the following compiler warnings:
> >
> >g++ -DG_LOG_DOMAIN=\"SFI\" -DG_DISABLE_CONST_RETURNS 
> >-I/home/stefan/src/beast -I.. -pthread -I/usr/include/glib-2.0
> >-I/usr/lib/glib-2.0/include  -g -DG_ENABLE_DEBUG -Wdeprecated -Wall 
> >-Wno-cast-qual -pipe -O2 -ftracer -finline-functions
> >-fno-keep-static-consts -fmessage-length=156 -c 
> >/home/stefan/src/beast/sfi/sfidl-parser.cc
> >/home/stefan/src/beast/sfi/sfidl-parser.cc: In member function `GTokenType 
> >Sfidl::Parser::parseStringOrConst(std::string&)':
> >/home/stefan/src/beast/sfi/sfidl-parser.cc:987: warning: long long int 
> >format, gint64 arg (arg 2)
> 
> no. while i'm currently not able to tell you what else to do to get
> rid of these warnings, i believe G_GINT64_FORMAT to not be the solution.
> 
> for one, scattering format strings with G_GINT64_FORMAT makes the code
> utterly unreadable, and for another, it doesn't properly cooperate with
> i18n of strings either. (you don't translate "foo error: %lld < 0" twice
> into all languages, once for %lld and once for %ld).
> 
> platform changes should not require format strings to change, if that
> is the case, it's a bug and needs to be fixed (prolly somewhere in 
> glibc/gcc).

Well, the problem is that the C Standard (however, my understanding of
the standard may be limited) only specifies printf format specifiers for
C types, such as int, long and long long. Those, however, do not have a
length guarantee. This is why glib defines its own data types, such as
gint64 and guint64. However, they do not correspond to a C type; or
rather, they do not correspond to _the same_ C type on each platform.

Thus, there is no printf format specifier for this. So what are the
alternatives that I see now?

 * do not use gint64 and guint64 in BEAST, but rather our own typedef
   (such as SfiNum) which then can be defined to long long

   this currently works, as long long is 64bit on all platforms that I
   know of; however, as 128bit processors get introduced, platforms
   that have 64bit longs may have 128bit long longs.

 * continue using gint64 and guint64, but introduce a cast to long long
   whereever printf is used

   so

   guint64 foo = 5;
   printf ("foo=%lld\n", foo);

   becomes

   guint64 foo = 5;
   printf ("foo=%lld\n", (unsigned long long)foo);

   this should work on any platform, even when 128bit long longs are
   introduced

 * implement a C++ based mechanism for format strings based on
   overloaded methods, such as QString::arg()

   http://doc.trolltech.com/3.3/qstring.html#arg-2

   then, the above example would read something like

   puts (Sfi::String("foo=%1").arg(foo).c_str());

   or

   cout << Sfi::String ("foo=%1\n").arg(foo);

   where Sfi::String would subclass std::string and add the arg() method
   or implement some string stuff itself and provide conversion operators
   to/from std::string; in the latter case, one could also call it
   FormatString ("foo=%1").arg(foo), if it is not intended to be used as
   string class for other tasks

 * use "cout << foo << endl;" however, this will not really work with i18n
   either, so I suppose it is not an option

Note that I have intentionally also suggested options which have C++
porting of all (much) code as precondition, because I intend to port
things anyway. Thus it doesn't make much difference on whether to port
first, and then fix the warnings, or do it the other way round, from the
perspective of the final result.

   Cu... Stefan
-- 
Stefan Westerfeld, Hamburg/Germany, http://space.twc.de/~stefan



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