printf() error with long double and null pointer.

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • fieldfallow

    printf() error with long double and null pointer.

    Hello all,

    Before stating my question, I should mention that I'm fairly new to C.

    Now, I attempted a small demo that prints out the values of C's numeric
    types, both uninitialised and after assigning them their maximum defined
    values. However, the output of printf() for the long double 'ld' and the
    pointer of type void 'v_p', after initialisation don't seem to be right.

    The compiler used was gcc (mingw) with '-Wall', '-std=c99' and
    '-pedantic' switches. No warnings were emitted. Incidentally the MS
    Visual C++ 2003 compiler's output seems okay. I give them both below:

    gcc's output:
    ld == -1.#QNAN0
    or -1.#QNAN
    v_p == FFFFFFFF

    msvc's output:
    ld == 179769313486231 570000000000000 000000000000000 000000000000000 000000
    000000000000000 000000000000000 000000000000000 000000000000000 000000000000
    000000000000000 000000000000000 000000000000000 000000000000000 000000000000
    000000000000000 000000000000000 000000000000000 000000000000000 000000000000
    000000000000000 000000000000.00 0000
    or 1.79769e+308
    v_p == 00000000

    I thought null pointers had a value of zero. Why is gcc's executable
    printing ffffffffh? Also the value of 'ld' seems to be wrong.

    The code for the demo is:
    #include <stdio.h>
    #include <limits.h>
    #include <float.h>

    int main(void) {
    char c;
    unsigned char uc;
    short s;
    unsigned short us;
    int i;
    unsigned int ui;
    long l;
    unsigned long ul;
    float f;
    double d;
    long double ld;
    void *v_p;

    printf("c == %c\n\tor %d\nuc == %c\n\tor %u\ns == %hd\nus == %hu\n"
    "i == %d\nui == %u\nl == %ld\nul == %lu\nf == %f\n\tor %g\n"
    "d == %lf\n\tor %g\nld == %Lf\n\tor %Lg\nv_p == %p\n",
    c,c,uc,uc,s,us, i,ui,l,ul,f,f,d ,d,ld,ld,v_p);

    puts("Initialis ing them with their maximum allowed values...");
    c = CHAR_MAX;
    uc = UCHAR_MAX;
    s = SHRT_MAX;
    us = USHRT_MAX;
    i = INT_MAX;
    ui = UINT_MAX;
    l = LONG_MAX;
    ul = ULONG_MAX;
    f = FLT_MAX;
    d = DBL_MAX;
    ld = LDBL_MAX;
    puts("Initialis ing v_p with NULL...");
    v_p = NULL;

    printf("c == %c\n\tor %d\nuc == %c\n\tor %u\ns == %hd\nus == %hu\n"
    "i == %d\nui == %u\nl == %ld\nul == %lu\nf == %f\n\tor %g\n"
    "d == %lf\n\tor %g\nld == %Lf\n\tor %Lg\nv_p == %p\n",
    c,c,uc,uc,s,us, i,ui,l,ul,f,f,d ,d,ld,ld,v_p);
    return 0;
    }

    Where is the mistake?
    Thanks for all the help.
  • A. Sinan Unur

    #2
    Re: printf() error with long double and null pointer.

    fieldfallow <fieldfallow@gm ail.com> wrote in news:dtmt1n$1g3 $1
    @emma.aioe.org:
    [color=blue]
    > I thought null pointers had a value of zero. Why is gcc's executable
    > printing ffffffffh?[/color]



    Sinan
    --
    A. Sinan Unur <1usa@llenroc.u de.invalid>
    (reverse each component and remove .invalid for email address)

    Comment

    • pete

      #3
      Re: printf() error with long double and null pointer.

      fieldfallow wrote:[color=blue]
      >
      > Hello all,
      >
      > Before stating my question,
      > I should mention that I'm fairly new to C.
      >
      > Now, I attempted a small demo that prints out
      > the values of C's numeric types, both uninitialised[/color]

      Accessing uninitialised values like that,
      causes undefined behavior in your program.
      The undefined behavior can show up in any part
      of the program's execution.

      --
      pete

      Comment

      • fieldfallow

        #4
        Re: printf() error with long double and null pointer.

        pete wrote:[color=blue]
        > fieldfallow wrote:[color=green]
        >> Hello all,
        >>
        >> Before stating my question,
        >> I should mention that I'm fairly new to C.
        >>
        >> Now, I attempted a small demo that prints out
        >> the values of C's numeric types, both uninitialised[/color]
        >
        > Accessing uninitialised values like that,
        > causes undefined behavior in your program.
        > The undefined behavior can show up in any part
        > of the program's execution.[/color]

        Does even printing out the values cause undefined behaviour? Is any
        other operation legal, or must I assign them values before I do anything
        with them?

        Thanks for your answers. The C book I currently have is not very clear
        on this point.

        Comment

        • Robin Haigh

          #5
          Re: printf() error with long double and null pointer.



          "fieldfallo w" <fieldfallow@gm ail.com> wrote in message
          news:dtmt1n$1g3 $1@emma.aioe.or g...[color=blue]
          > Hello all,
          >
          > Before stating my question, I should mention that I'm fairly new to C.
          >
          > Now, I attempted a small demo that prints out the values of C's numeric
          > types, both uninitialised and after assigning them their maximum defined
          > values. However, the output of printf() for the long double 'ld' and the
          > pointer of type void 'v_p', after initialisation don't seem to be right.
          >
          > The compiler used was gcc (mingw) with '-Wall', '-std=c99' and
          > '-pedantic' switches. No warnings were emitted. Incidentally the MS
          > Visual C++ 2003 compiler's output seems okay. I give them both below:
          >
          > gcc's output:
          > ld == -1.#QNAN0
          > or -1.#QNAN
          > v_p == FFFFFFFF
          >
          > msvc's output:
          > ld == 179769313486231 570000000000000 000000000000000 000000000000000 000000
          > 000000000000000 000000000000000 000000000000000 000000000000000 000000000000
          > 000000000000000 000000000000000 000000000000000 000000000000000 000000000000
          > 000000000000000 000000000000000 000000000000000 000000000000000 000000000000
          > 000000000000000 000000000000.00 0000
          > or 1.79769e+308
          > v_p == 00000000
          >
          > I thought null pointers had a value of zero. Why is gcc's executable
          > printing ffffffffh? Also the value of 'ld' seems to be wrong.
          >
          > The code for the demo is:
          > #include <stdio.h>
          > #include <limits.h>
          > #include <float.h>
          >
          > int main(void) {
          > char c;
          > unsigned char uc;
          > short s;
          > unsigned short us;
          > int i;
          > unsigned int ui;
          > long l;
          > unsigned long ul;
          > float f;
          > double d;
          > long double ld;
          > void *v_p;
          >
          > printf("c == %c\n\tor %d\nuc == %c\n\tor %u\ns == %hd\nus == %hu\n"
          > "i == %d\nui == %u\nl == %ld\nul == %lu\nf == %f\n\tor %g\n"
          > "d == %lf\n\tor %g\nld == %Lf\n\tor %Lg\nv_p == %p\n",
          > c,c,uc,uc,s,us, i,ui,l,ul,f,f,d ,d,ld,ld,v_p);
          >
          > puts("Initialis ing them with their maximum allowed values...");
          > c = CHAR_MAX;
          > uc = UCHAR_MAX;
          > s = SHRT_MAX;
          > us = USHRT_MAX;
          > i = INT_MAX;
          > ui = UINT_MAX;
          > l = LONG_MAX;
          > ul = ULONG_MAX;
          > f = FLT_MAX;
          > d = DBL_MAX;
          > ld = LDBL_MAX;
          > puts("Initialis ing v_p with NULL...");
          > v_p = NULL;
          >
          > printf("c == %c\n\tor %d\nuc == %c\n\tor %u\ns == %hd\nus == %hu\n"
          > "i == %d\nui == %u\nl == %ld\nul == %lu\nf == %f\n\tor %g\n"
          > "d == %lf\n\tor %g\nld == %Lf\n\tor %Lg\nv_p == %p\n",
          > c,c,uc,uc,s,us, i,ui,l,ul,f,f,d ,d,ld,ld,v_p);
          > return 0;
          > }
          >
          > Where is the mistake?
          > Thanks for all the help.[/color]

          Works for me running gcc on Cygwin.

          %lf (alternative to %f) for double is a new feature in C99. Does your
          printf support it?

          If you're not on Linux or Cygwin, you may be using your system's libc, in
          which case you get what you get, notwithstanding the C99 flag.


          --
          RSH


          Comment

          • pete

            #6
            Re: printf() error with long double and null pointer.

            fieldfallow wrote:[color=blue]
            >
            > pete wrote:[color=green]
            > > fieldfallow wrote:[color=darkred]
            > >> Hello all,
            > >>
            > >> Before stating my question,
            > >> I should mention that I'm fairly new to C.
            > >>
            > >> Now, I attempted a small demo that prints out
            > >> the values of C's numeric types, both uninitialised[/color]
            > >
            > > Accessing uninitialised values like that,
            > > causes undefined behavior in your program.
            > > The undefined behavior can show up in any part
            > > of the program's execution.[/color]
            >
            > Does even printing out the values cause undefined behaviour?[/color]

            Yes.
            [color=blue]
            > Is any
            > other operation legal, or must I assign them values before I do
            > anything with them?[/color]

            For uninitialised objects,
            you can only portably do operations which don't access the values.
            That's pretty much limited to having the variables be
            operands of the address operator and or the sizeof operator.

            --
            pete

            Comment

            • Richard Tobin

              #7
              Re: printf() error with long double and null pointer.

              In article <dtmvse$km3$1@e mma.aioe.org>,
              fieldfallow <fieldfallow@gm ail.com> wrote:
              [color=blue][color=green]
              >> Accessing uninitialised values like that,
              >> causes undefined behavior in your program.
              >> The undefined behavior can show up in any part
              >> of the program's execution.[/color][/color]
              [color=blue]
              >Does even printing out the values cause undefined behaviour?[/color]

              Yes, but I would be surprised if it caused the behaviour shown.
              Try removing the first printf and see if you still get the same
              results for the second.

              -- Richard

              Comment

              • fieldfallow

                #8
                Re: printf() error with long double and null pointer.

                Richard Tobin wrote:[color=blue]
                > In article <dtmvse$km3$1@e mma.aioe.org>,
                > fieldfallow <fieldfallow@gm ail.com> wrote:
                >[color=green][color=darkred]
                >>> Accessing uninitialised values like that,
                >>> causes undefined behavior in your program.
                >>> The undefined behavior can show up in any part
                >>> of the program's execution.[/color][/color]
                >[color=green]
                >> Does even printing out the values cause undefined behaviour?[/color]
                >
                > Yes, but I would be surprised if it caused the behaviour shown.
                > Try removing the first printf and see if you still get the same
                > results for the second.[/color]

                Yes. Even after commenting out the first printf(), I still get the same
                wrong output. Would this indicate a fault in the particular toolchain,
                i.e. gcc (MinGW)?

                The output is:
                Initialising them with their maximum allowed values...
                Initialising v_p with NULL...
                c == 
                or 127
                uc == ΓΏ
                or 255
                s == 32767
                us == 65535
                i == 2147483647
                ui == 4294967295
                l == 2147483647
                ul == 4294967295
                f == 340282346638528 860000000000000 000000000.00000 0
                or 3.40282e+038
                d == 179769313486231 570000000000000 000000000000000 000000000000000 00000000
                000000000000000 000000000000000 000000000000000 000000000000000 00000000
                000000000000000 000000000000000 000000000000000 000000000000000 00000000
                000000000000000 000000000000000 000000000000000 000000000000000 00000000
                000000000000000 000000000000000 0000000.000000
                or 1.79769e+308
                ld == -1.#QNAN0
                or -1.#QNAN
                v_p == FFFFFFFF

                Thanks.

                Comment

                • pete

                  #9
                  Re: printf() error with long double and null pointer.

                  fieldfallow wrote:
                  [color=blue]
                  > ld == -1.#QNAN0
                  > or -1.#QNAN[/color]

                  That result is also wrong.

                  Are you using still using %lf to output doubles?

                  %f is for both doubles and floats.

                  C99 allows %lf for doubles, but most compilers are C90
                  where using %lf to output a double is also undefined.

                  --
                  pete

                  Comment

                  • fieldfallow

                    #10
                    Re: printf() error with long double and null pointer.

                    Robin Haigh wrote:[color=blue]
                    > Works for me running gcc on Cygwin.[/color]

                    Strange. My compiler is gcc 3.4.5 for MinGW 5.0
                    [color=blue]
                    > %lf (alternative to %f) for double is a new feature in C99. Does your
                    > printf support it?[/color]

                    I think so. The output for the double seems to be correct. Only those of
                    the long double and void pointer seem to be wrong. I'm saying this
                    because the MS Visual C++ 2003 toolkit compiler's output for the double
                    tallies with gcc. In addition the max. for long double is the same as
                    double and void pointer prints out zero after assigning NULL to it.
                    [color=blue]
                    > If you're not on Linux or Cygwin, you may be using your system's libc, in
                    > which case you get what you get, notwithstanding the C99 flag.[/color]

                    In this case, the MSVC compiled executable should also exhibit the same
                    error, shouldn't it.

                    Anyway, this seems to be heading a bit off-topic here. Maybe a MinGW
                    group would be better.

                    Thanks everyone for your help.

                    Comment

                    • Richard Tobin

                      #11
                      Re: printf() error with long double and null pointer.

                      In article <43FF1048.10506 09@gmail.com>,
                      fieldfallow <fieldfallow@gm ail.com> wrote:
                      [color=blue]
                      >Yes. Even after commenting out the first printf(), I still get the same
                      >wrong output. Would this indicate a fault in the particular toolchain,
                      >i.e. gcc (MinGW)?[/color]

                      Perhaps a bug in the handling of long double. Take out the long
                      double values and see if the pointer has the expected value. Or put
                      in some plain integers after the long doubles and see if they are
                      wrong. (As far as I know, %p is not required to print any particular
                      value for null pointers, but it will almost certainly be zero.)

                      -- Richard

                      Comment

                      • pete

                        #12
                        Re: printf() error with long double and null pointer.

                        pete wrote:[color=blue]
                        >
                        > fieldfallow wrote:
                        >[color=green]
                        > > ld == -1.#QNAN0
                        > > or -1.#QNAN[/color]
                        >
                        > That result is also wrong.
                        >
                        > Are you using still using %lf to output doubles?
                        >
                        > %f is for both doubles and floats.
                        >
                        > C99 allows %lf for doubles, but most compilers are C90
                        > where using %lf to output a double is also undefined.[/color]

                        I'm suggesting that the error may have occured just
                        before the long double output.

                        --
                        pete

                        Comment

                        • fieldfallow

                          #13
                          Re: printf() error with long double and null pointer.

                          pete wrote:[color=blue]
                          > fieldfallow wrote:
                          >[color=green]
                          >> ld == -1.#QNAN0
                          >> or -1.#QNAN[/color]
                          >
                          > That result is also wrong.
                          >
                          > Are you using still using %lf to output doubles?
                          >
                          > %f is for both doubles and floats.
                          >
                          > C99 allows %lf for doubles, but most compilers are C90
                          > where using %lf to output a double is also undefined.[/color]

                          Okay, I switched to %f for both floats and doubles and kept the first
                          printf() commented out, and still the same error.

                          Output:
                          Initialising them with their maximum allowed values...
                          Initialising v_p with NULL...
                          c == 
                          or 127
                          uc == ΓΏ
                          or 255
                          s == 32767
                          us == 65535
                          i == 2147483647
                          ui == 4294967295
                          l == 2147483647
                          ul == 4294967295
                          f == 340282346638528 860000000000000 000000000.00000 0
                          or 3.40282e+038
                          d == 179769313486231 570000000000000 000000000000000 000000
                          000000000000000 000000000000000 000000000000000 00000000000
                          000000000000000 000000000000000 000000000000000 00000000000
                          000000000000000 000000000000000 000000000000000 00000000000
                          000000000000000 000000000000000 000000000000000 00000000000
                          000000000000000 000000000000000 0000.000000
                          or 1.79769e+308
                          ld == -1.#QNAN0
                          or -1.#QNAN
                          v_p == FFFFFFFF

                          Code is:
                          #include <stdio.h>
                          #include <limits.h>
                          #include <float.h>

                          int main(void) {
                          char c;
                          unsigned char uc;
                          short s;
                          unsigned short us;
                          int i;
                          unsigned int ui;
                          long l;
                          unsigned long ul;
                          float f;
                          double d;
                          long double ld;
                          void *v_p;
                          /*
                          printf("c == %c\n\tor %d\nuc == %c\n\tor %u\ns == %hd\nus == %hu\n"
                          "i == %d\nui == %u\nl == %ld\nul == %lu\nf == %f\n\tor %g\n"
                          "d == %lf\n\tor %g\nld == %Lf\n\tor %Lg\nv_p == %p\n",
                          c,c,uc,uc,s,us, i,ui,l,ul,f,f,d ,d,ld,ld,v_p);
                          */
                          puts("Initialis ing them with their maximum allowed values...");
                          c = CHAR_MAX;
                          uc = UCHAR_MAX;
                          s = SHRT_MAX;
                          us = USHRT_MAX;
                          i = INT_MAX;
                          ui = UINT_MAX;
                          l = LONG_MAX;
                          ul = ULONG_MAX;
                          f = FLT_MAX;
                          d = DBL_MAX;
                          ld = LDBL_MAX;
                          puts("Initialis ing v_p with NULL...");
                          v_p = NULL;

                          printf("c == %c\n\tor %d\nuc == %c\n\tor %u\ns == %hd\nus == %hu\n"
                          "i == %d\nui == %u\nl == %ld\nul == %lu\nf == %f\n\tor %g\n"
                          "d == %f\n\tor %g\nld == %Lf\n\tor %Lg\nv_p == %p\n",
                          c,c,uc,uc,s,us, i,ui,l,ul,f,f,d ,d,ld,ld,v_p);
                          return 0;
                          }

                          Thanks.

                          Comment

                          • fieldfallow

                            #14
                            Re: printf() error with long double and null pointer.

                            Richard Tobin wrote:[color=blue]
                            > In article <43FF1048.10506 09@gmail.com>,
                            > fieldfallow <fieldfallow@gm ail.com> wrote:
                            >[color=green]
                            >> Yes. Even after commenting out the first printf(), I still get the same
                            >> wrong output. Would this indicate a fault in the particular toolchain,
                            >> i.e. gcc (MinGW)?[/color]
                            >
                            > Perhaps a bug in the handling of long double. Take out the long
                            > double values and see if the pointer has the expected value. Or put
                            > in some plain integers after the long doubles and see if they are
                            > wrong. (As far as I know, %p is not required to print any particular
                            > value for null pointers, but it will almost certainly be zero.)
                            >
                            > -- Richard[/color]

                            Your right Richard. After completely removing the long double from
                            printf(), the void pointer's value is printed out as 00000000.

                            Also, declaring and initialising the long double with LDBL_MAX, but not
                            attempting to pass it to printf() also gives the correct output for the
                            void pointer.

                            So I guess it appears to be a bug in the printf()'s handling of long
                            double arguments.

                            Maybe it's been corrected by any recent patches, though my MinGW
                            distribution was installed only two months before.

                            Thanks for your help.

                            Comment

                            • Richard Bos

                              #15
                              Re: printf() error with long double and null pointer.

                              fieldfallow <fieldfallow@gm ail.com> wrote:
                              [color=blue]
                              > Richard Tobin wrote:[color=green]
                              > > In article <dtmvse$km3$1@e mma.aioe.org>,
                              > > fieldfallow <fieldfallow@gm ail.com> wrote:
                              > >[color=darkred]
                              > >>> Accessing uninitialised values like that,
                              > >>> causes undefined behavior in your program.
                              > >>> The undefined behavior can show up in any part
                              > >>> of the program's execution.[/color]
                              > >[color=darkred]
                              > >> Does even printing out the values cause undefined behaviour?[/color]
                              > >
                              > > Yes, but I would be surprised if it caused the behaviour shown.
                              > > Try removing the first printf and see if you still get the same
                              > > results for the second.[/color]
                              >
                              > Yes. Even after commenting out the first printf(), I still get the same
                              > wrong output.[/color]

                              It does that for me, too[0]. When I remove the references to long
                              doubles in the printf(), it prints the expected[1] value for v_p, too.
                              It appears at first glance that gcc and the MinGW library are not in
                              accord over the size of a long double. How pernicious.

                              Try this: print (using sizeof) the size of your double and long double.
                              Dev-C++ on this computer says 8 and 12, respectively. But the headers
                              claim that long double is the same as double, and all values in
                              <float.h> for LDBL_* are the same as for DBL_*. Presumably, *printf()
                              assume that sizeof (double) == sizeof (long double), too.
                              [color=blue]
                              > Would this indicate a fault in the particular toolchain, i.e. gcc (MinGW)?[/color]

                              Yes.

                              Anyone know the right channel to report this to MinGW?

                              Richard

                              [0] Even when inserting the l in the second %g...
                              [1] Although not required.

                              Comment

                              Working...