scanf makes exponents specifiers mandatory whereas it should not. The code to reproduce the problem is: #include <stdio.h> int main (void) { double d = -999; int ret; ret = sscanf ("0x100", "%lg", &d); printf ("%d %g\n", ret, d); ret = sscanf ("0x100p0", "%lg", &d); printf ("%d %g\n", ret, d); return 0; } expected output would be: 1 256 1 256 it gives currently: 0 -999 1 256
That's how *scanf initially worked, till the 1999-08-13 Ulrich Drepper <drepper@cygnus.com> * stdio-common/tstscanf.c: Add test for hexadecimal float parsing problem. * stdio-common/vfscanf.c: Don't recognize hexadecimal floats without exponent. --- stdio-common/vfscanf.c 21 Jun 1999 13:35:40 -0000 1.67 +++ stdio-common/vfscanf.c 13 Aug 1999 19:41:26 -0000 1.68 @@ -1410,8 +1410,8 @@ __vfscanf (FILE *s, const char *format, /* Have we read any character? If we try to read a number in hexadecimal notation and we have read only the `0x' - prefix this is an error. */ - if (wpsize == 0 || (is_hexa && wpsize == 2)) + prefix or no exponent this is an error. */ + if (wpsize == 0 || (is_hexa && (wpsize == 2 || ! got_e))) conv_error (); scan_float: --- stdio-common/tstscanf.c 6 Jun 1999 09:18:57 -0000 1.12 +++ stdio-common/tstscanf.c 13 Aug 1999 22:39:01 -0000 1.13 @@ -250,5 +250,20 @@ main (int argc, char **argv) } } + fputs ("Test 8:\n", stdout); + { + double d = 123456.789; + int res; + + res = sscanf ("0x1234", "%lf", &d); + printf ("res = %d, d = %f\n", res, d); + + if (res != 0 || d != 123456.789) + { + fputs ("test failed!\n", stdout); + result = 1; + } + } + exit (result); } change. My reading of both ISO C99 and current POSIX suggests that indeed the exponent is only optional. While ISO C99 has a footnote: "fscanf pushes back at most one input character onto the input stream. Therefore, some sequences that are acceptable to strtod, strtol, etc., are unacceptable to fscanf." I don't think this applies here, as the hexadecimal float exponent part is structured the same as decimal exponent part, just with a different letter (p vs. e) and as the decimal float has the exponent part optional, there is no reason why it couldn't be optional even for hexadecimal floats.
I changed the code in cvs.
Subject: Bug 4342 CVSROOT: /cvs/glibc Module name: libc Branch: glibc-2_5-branch Changes by: jakub@sourceware.org 2007-07-12 15:13:48 Modified files: . : ChangeLog stdio-common : tstscanf.c vfscanf.c Log message: 2007-04-27 Ulrich Drepper <drepper@redhat.com> [BZ #4342] * stdio-common/vfscanf.c (_IO_vfscanf_internal): Allow hexa-decimal floats without exponent. * stdio-common/tstscanf.c (main): Adjust Test 8 test for success. Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/libc/ChangeLog.diff?cvsroot=glibc&only_with_tag=glibc-2_5-branch&r1=1.10362.2.75&r2=1.10362.2.76 http://sourceware.org/cgi-bin/cvsweb.cgi/libc/stdio-common/tstscanf.c.diff?cvsroot=glibc&only_with_tag=glibc-2_5-branch&r1=1.21&r2=1.21.10.1 http://sourceware.org/cgi-bin/cvsweb.cgi/libc/stdio-common/vfscanf.c.diff?cvsroot=glibc&only_with_tag=glibc-2_5-branch&r1=1.115&r2=1.115.2.1