skip to Main Content

Consider the following program:

#include <stdio.h>

// [Example 5 from C17; Page 238](https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2310.pdf)

int main(void) {
  int n = 0;
  int i = 0;

  n = sscanf("foo %bar 42", "foo%%bar%d", &i);

  printf("n = %dni = %dn", n, i);

  return 0;
}

According to the C17 Standard, it should print

n = 1
i = 42

However, on my platform it prints

n = 0
i = 0

gcc -v on my platform gives:

Using built-in specs.
COLLECT_GCC=D:mingw64bingcc.exe
COLLECT_LTO_WRAPPER=d:/mingw64/bin/../libexec/gcc/x86_64-w64-mingw32/12.1.0/lto-wrapper.exe
OFFLOAD_TARGET_NAMES=nvptx-none
Target: x86_64-w64-mingw32
Configured with: ../configure --prefix=/R/winlibs64-11.3.0ucrt/inst_gcc-12.1.0/share/gcc --build=x86_64-w64-mingw32 --host=x86_64-w64-mingw32 --enable-offload-targets=nvptx-none --with-pkgversion='MinGW-W64 x86_64-ucrt-posix-seh, built by Brecht Sanders' --with-tune=generic --enable-checking=release --enable-threads=posix --disable-sjlj-exceptions --disable-libunwind-exceptions --disable-serial-configure --disable-bootstrap --enable-host-shared --enable-plugin --disable-default-ssp --disable-rpath --disable-libstdcxx-debug --disable-version-specific-runtime-libs --with-stabs --disable-symvers --enable-languages=c,c++,fortran,lto,objc,obj-c++,jit --disable-gold --disable-nls --disable-stage1-checking --disable-win32-registry --disable-multilib --enable-ld --enable-libquadmath --enable-libada --enable-libssp --enable-libstdcxx --enable-lto --enable-fully-dynamic-string --enable-libgomp --enable-graphite --enable-mingw-wildcard --enable-libstdcxx-time --disable-libstdcxx-pch --with-mpc=/e/Prog/wi
nlibs64-11.3.0ucrt/custombuilt --with-mpfr=/e/Prog/winlibs64-11.3.0ucrt/custombuilt --with-gmp=/e/Prog/winlibs64-11.3.0ucrt/cu
stombuilt --with-isl=/e/Prog/winlibs64-11.3.0ucrt/custombuilt --enable-libstdcxx-backtrace --enable-install-libiberty --enable
-__cxa_atexit --without-included-gettext --with-diagnostics-color=auto --enable-clocale=generic --with-libiconv --with-system-
zlib --with-build-sysroot=/R/winlibs64-11.3.0ucrt/gcc-12.1.0/build_mingw/mingw-w64 CFLAGS='-I/e/Prog/winlibs64-11.3.0ucrt/cust
ombuilt/include/libdl-win32 -D__USE_MINGW_ACCESS' CXXFLAGS=-D__USE_MINGW_ACCESS LDFLAGS='-Wl,--disable-nxcompat -Wl,--disable-high-entropy-va -Wl,--disable-dynamicbase'
Thread model: posix
Supported LTO compression algorithms: zlib zstd
gcc version 12.1.0 (MinGW-W64 x86_64-ucrt-posix-seh, built by Brecht Sanders)

ADDED:
I tried another platform, it does print

n = 1
i = 42

On this platform, gcc -v shows:

Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/11/lto-wrapper
OFFLOAD_TARGET_NAMES=nvptx-none:amdgcn-amdhsa
OFFLOAD_TARGET_DEFAULT=1
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 11.4.0-1ubuntu1~22.04' --with-bugurl
=file:///usr/share/doc/gcc-11/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c
++,m2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-11 --program-prefix=x86_64-linu
ithout-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu --with-build-config=bootstrap-lto-lean --enable-link-serialization=2
ithout-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu --with-build-config=bootstrap-lto-lean --enable-link-serialization=2
Thread model: posix
Supported LTO compression algorithms: zlib zstd
gcc version 11.4.0 (Ubuntu 11.4.0-1ubuntu1~22.04)
ithout-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu --with-build-config=bootstrap-lto-lean --enable-link-serialization=2
ithout-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu --with-build-config=bootstrap-lto-lean --enable-link-serialization=2
Thread model: posix
Supported LTO compression algorithms: zlib zstd
gcc version 11.4.0 (Ubuntu 11.4.0-1ubuntu1~22.04)

So it seems that this is a bug of the compiler on the first platform?

2

Answers


  1. The behavior of your first platform does not conform to the C standard. C 2018 7.21.6.2 7 and 8 say:

    A directive that is a conversion specification defines a set of matching input sequences, as described below for each specifier. A conversion specification is executed in the following steps:

    Input white-space characters (as specified by the isspace function) are skipped, unless the specification includes a [, c, or n specifier.

    %% is a conversion specification (because 7.21.6.2 3 says the format string is composed of directives which are one or more white-space characters, an ordinary multibyte character, or a conversion specification, and that each conversion specification is introduced by the character %) and does not include [, c, or n, so input white-space characters before it should be skipped.

    Equivalent language appears in versions of the standard going back to 1990.

    You should test compiling with -std=c17 just in case there is some issue with default compilations using the C library in a non-conforming mode. (I do not think that is likely, but it is theoretically possible.)

    Login or Signup to reply.
  2. 7.21.6.2 The fscanf function (which shares definition with sscanf except for where the input comes from part):

    1. Input white-space characters (as specified by the function) are skipped, unless the specification includes a [, c, or n specifier.

    Since your specification does not include one of the specifiers included in the exception list, sscanf should skip the whitespaces. My conclusion is that the implementation of sscanf on your platform is wrong.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search