Printf question.

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

    Printf question.

    Hi,

    I was wondering something today. The following code :

    unsigned char a = 200;
    char b = 200;
    printf( "%d %d", a, b );

    gives :

    200, -56

    How comes? I didn't tell printf that the first argument was unsigned
    and it detected it on its own. It doesn't seem possible with varargs.
    How is it possible?

    Thanks,

  • usenet@zevv.nl

    #2
    Re: Printf question.

    praeiji <spacecaps@gmai l.com> wrote:[color=blue]
    >
    > unsigned char a = 200;
    > char b = 200;
    > printf( "%d %d", a, b );
    >
    > gives :
    >
    > 200, -56
    >
    > How comes? I didn't tell printf that the first argument was unsigned
    > and it detected it on its own. It doesn't seem possible with varargs.
    > How is it possible?[/color]

    Both arguments get promoted to int before they are passed to printf()

    _Ico

    --
    :wq
    ^X^Cy^K^X^C^C^C ^C

    Comment

    • praeiji

      #3
      Re: Printf question.

      Thanks,

      But why are they typecasted to int? Does it come from gcc when it sees
      "%d" and the printf function?

      Comment

      • nelu

        #4
        Re: Printf question.


        praeiji wrote:[color=blue]
        > Hi,
        >
        > I was wondering something today. The following code :
        >
        > unsigned char a = 200;
        > char b = 200;
        > printf( "%d %d", a, b );
        >
        > gives :
        >
        > 200, -56
        >
        > How comes? I didn't tell printf that the first argument was unsigned
        > and it detected it on its own. It doesn't seem possible with varargs.
        > How is it possible?
        >
        > Thanks,[/color]

        Conversion Argument Converted Default Pre-
        Specifier Type Value Base cision
        %d int x (int)x 10 1

        That means %d formats int. If you give it char and unsigned char it
        will convert them to int.

        Comment

        • Jack Klein

          #5
          Re: Printf question.

          On 30 Dec 2005 11:21:25 -0800, "praeiji" <spacecaps@gmai l.com> wrote
          in comp.lang.c:
          [color=blue]
          > Hi,
          >
          > I was wondering something today. The following code :
          >
          > unsigned char a = 200;
          > char b = 200;
          > printf( "%d %d", a, b );
          >
          > gives :
          >
          > 200, -56
          >
          > How comes? I didn't tell printf that the first argument was unsigned
          > and it detected it on its own. It doesn't seem possible with varargs.
          > How is it possible?
          >
          > Thanks,[/color]

          This has nothing to do with printf(), per se. It does not know the
          difference between the original objects providing the values.

          What you are seeing is the result of what the C standard calls the
          "default argument promotions". These occur when calling a function
          without a prototype in scope, or for the "..." arguments in a variadic
          function.

          In the case of integer types of lesser rank than int, the "integer
          promotions" occur. Since a signed int can hold the value 200, the
          value in the unsigned char 'a' is converted to the int value 200.

          On your particular system, chars have 8 bits and 'plain' char is
          signed. The binary representation of 200 in an 8-bit byte happens to
          be the same as the 8-bit 2's complement representation of -56, and
          that is the implementation-defined result of assigning the
          out-of-range value to a signed 'plain' char.

          The integer promotions take the 'plain' char value of -56 and convert
          it to an int value of -56.

          So the values of 200 and -56 are generated during argument evaluation,
          before printf() is called.

          On some platforms, char has more than 8 bits, and 200 would remain 200
          in a 'plain' char or signed char. On some platforms, 'plain' char is
          unsigned, not signed. On platforms with either of these
          characteristics , the output would be "200, 200".

          And on some platforms, the output would not appear at all because you
          did not add a final '\n'.

          --
          Jack Klein
          Home: http://JK-Technology.Com
          FAQs for
          comp.lang.c http://c-faq.com/
          comp.lang.c++ http://www.parashift.com/c++-faq-lite/
          alt.comp.lang.l earn.c-c++

          Comment

          • praeiji

            #6
            Re: Printf question.

            thank you :)

            Silly me, I'd never heard of the "integer promotions" before.

            Comment

            • usenet@zevv.nl

              #7
              Re: Printf question.

              praeiji <spacecaps@gmai l.com> wrote:
              [color=blue]
              > But why are they typecasted to int? Does it come from gcc when it sees
              > "%d" and the printf function?[/color]

              No, they are not typecasted, but `promoted', which is not the same thing.
              Promotion is what happens when you call a function that has no prototype, or
              when a function with a variable number (variadic) of arguments like printf()
              is called. With promotion, all arguments are converted to a generic 'bigger'
              type: char and short to int, float to double.

              Ico

              --
              :wq
              ^X^Cy^K^X^C^C^C ^C

              Comment

              • Keith Thompson

                #8
                Re: Printf question.

                Jack Klein <jackklein@spam cop.net> writes:[color=blue]
                > On 30 Dec 2005 11:21:25 -0800, "praeiji" <spacecaps@gmai l.com> wrote
                > in comp.lang.c:[/color]
                [...][color=blue][color=green]
                >> unsigned char a = 200;
                >> char b = 200;
                >> printf( "%d %d", a, b );
                >>
                >> gives :
                >>
                >> 200, -56
                >>
                >> How comes? I didn't tell printf that the first argument was unsigned
                >> and it detected it on its own. It doesn't seem possible with varargs.
                >> How is it possible?[/color][/color]
                [snip]
                [color=blue]
                > In the case of integer types of lesser rank than int, the "integer
                > promotions" occur. Since a signed int can hold the value 200, the
                > value in the unsigned char 'a' is converted to the int value 200.[/color]

                Correction: since a signed int can hold any value of type unsigned
                char, the value in the unsigned char 'a' is promoted to type int. The
                promoted type doesn't depend on the value that happens to be in the
                variable; it depends on which type can hold *any* possible value of
                the type.

                --
                Keith Thompson (The_Other_Keit h) kst-u@mib.org <http://www.ghoti.net/~kst>
                San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
                We must do something. This is something. Therefore, we must do this.

                Comment

                • Flash Gordon

                  #9
                  Re: Printf question.

                  Keith Thompson wrote:[color=blue]
                  > Jack Klein <jackklein@spam cop.net> writes:[color=green]
                  >> On 30 Dec 2005 11:21:25 -0800, "praeiji" <spacecaps@gmai l.com> wrote
                  >> in comp.lang.c:[/color]
                  > [...][color=green][color=darkred]
                  >>> unsigned char a = 200;
                  >>> char b = 200;
                  >>> printf( "%d %d", a, b );
                  >>>
                  >>> gives :
                  >>>
                  >>> 200, -56
                  >>>
                  >>> How comes? I didn't tell printf that the first argument was unsigned
                  >>> and it detected it on its own. It doesn't seem possible with varargs.
                  >>> How is it possible?[/color][/color]
                  > [snip]
                  >[color=green]
                  >> In the case of integer types of lesser rank than int, the "integer
                  >> promotions" occur. Since a signed int can hold the value 200, the
                  >> value in the unsigned char 'a' is converted to the int value 200.[/color]
                  >
                  > Correction: since a signed int can hold any value of type unsigned
                  > char, the value in the unsigned char 'a' is promoted to type int.[/color]

                  <annoying pedant>
                  What, even on a system with CHAR_BIT==16 and sizeof(int)==1 ?
                  </annoying pedant>

                  Of course, you are only likely to find such systems in the embedded
                  world where you may well not have printf.
                  [color=blue]
                  > The
                  > promoted type doesn't depend on the value that happens to be in the
                  > variable; it depends on which type can hold *any* possible value of
                  > the type.[/color]

                  You are, of course, correct that is is purely a matter of type, not the
                  value the variable happens to contain.
                  --
                  Flash Gordon
                  Living in interesting times.
                  Although my email address says spam, it is real and I read it.

                  Comment

                  • Charles Richmond

                    #10
                    Re: Printf question.

                    usenet@zevv.nl wrote:[color=blue]
                    >
                    > praeiji <spacecaps@gmai l.com> wrote:
                    >[color=green]
                    > > But why are they typecasted to int? Does it come from gcc when it sees
                    > > "%d" and the printf function?[/color]
                    >
                    > No, they are not typecasted, but `promoted', which is not the same thing.
                    > Promotion is what happens when you call a function that has no prototype, or
                    > when a function with a variable number (variadic) of arguments like printf()
                    > is called. With promotion, all arguments are converted to a generic 'bigger'
                    > type: char and short to int, float to double.
                    >[/color]
                    Type promotion can also happen when you do mixed mode arithmetic.

                    --
                    +----------------------------------------------------------------+
                    | Charles and Francis Richmond richmond at plano dot net |
                    +----------------------------------------------------------------+

                    Comment

                    • Jack Klein

                      #11
                      Re: Printf question.

                      On Fri, 30 Dec 2005 20:56:02 GMT, Keith Thompson <kst-u@mib.org> wrote
                      in comp.lang.c:
                      [color=blue]
                      > Jack Klein <jackklein@spam cop.net> writes:[color=green]
                      > > On 30 Dec 2005 11:21:25 -0800, "praeiji" <spacecaps@gmai l.com> wrote
                      > > in comp.lang.c:[/color]
                      > [...][color=green][color=darkred]
                      > >> unsigned char a = 200;
                      > >> char b = 200;
                      > >> printf( "%d %d", a, b );
                      > >>
                      > >> gives :
                      > >>
                      > >> 200, -56
                      > >>
                      > >> How comes? I didn't tell printf that the first argument was unsigned
                      > >> and it detected it on its own. It doesn't seem possible with varargs.
                      > >> How is it possible?[/color][/color]
                      > [snip]
                      >[color=green]
                      > > In the case of integer types of lesser rank than int, the "integer
                      > > promotions" occur. Since a signed int can hold the value 200, the
                      > > value in the unsigned char 'a' is converted to the int value 200.[/color]
                      >
                      > Correction: since a signed int can hold any value of type unsigned
                      > char, the value in the unsigned char 'a' is promoted to type int. The
                      > promoted type doesn't depend on the value that happens to be in the
                      > variable; it depends on which type can hold *any* possible value of
                      > the type.[/color]

                      Yes, thanks.

                      --
                      Jack Klein
                      Home: http://JK-Technology.Com
                      FAQs for
                      comp.lang.c http://c-faq.com/
                      comp.lang.c++ http://www.parashift.com/c++-faq-lite/
                      alt.comp.lang.l earn.c-c++

                      Comment

                      • Malcolm

                        #12
                        Re: Printf question.

                        "Flash Gordon" <spam@flash-gordon.me.uk> wrote[color=blue]
                        >[color=green]
                        >> Correction: since a signed int can hold any value of type unsigned
                        >> char, the value in the unsigned char 'a' is promoted to type int.[/color]
                        >
                        > <annoying pedant>
                        > What, even on a system with CHAR_BIT==16 and sizeof(int)==1 ?
                        > </annoying pedant>
                        >
                        > Of course, you are only likely to find such systems in the embedded world
                        > where you may well not have printf.
                        >[/color]
                        But often you have vsprintf(), or you need to implement it.

                        The whole language does begin to break down when we push the limits of
                        ANSI's definition. For instance, should field-length parameters really be
                        size_t s?



                        Comment

                        • Eric Sosman

                          #13
                          Re: Printf question.

                          Charles Richmond wrote:[color=blue]
                          > usenet@zevv.nl wrote:
                          >[color=green]
                          >>praeiji <spacecaps@gmai l.com> wrote:
                          >>
                          >>[color=darkred]
                          >>>But why are they typecasted to int? Does it come from gcc when it sees
                          >>>"%d" and the printf function?[/color]
                          >>
                          >>No, they are not typecasted, but `promoted', which is not the same thing.
                          >>Promotion is what happens when you call a function that has no prototype, or
                          >>when a function with a variable number (variadic) of arguments like printf()
                          >>is called. With promotion, all arguments are converted to a generic 'bigger'
                          >>type: char and short to int, float to double.
                          >>[/color]
                          >
                          > Type promotion can also happen when you do mixed mode arithmetic.[/color]

                          Or even unmixed-mode arithmetic:

                          short x = 1, y = 2;
                          short z = x + y; /* see the "int"? */

                          --
                          Eric Sosman
                          esosman@acm-dot-org.invalid

                          Comment

                          • Jordan Abel

                            #14
                            Re: Printf question.

                            On 2005-12-31, Malcolm <regniztar@btin ternet.com> wrote:[color=blue]
                            > "Flash Gordon" <spam@flash-gordon.me.uk> wrote[color=green]
                            >>[color=darkred]
                            >>> Correction: since a signed int can hold any value of type unsigned
                            >>> char, the value in the unsigned char 'a' is promoted to type int.[/color]
                            >>
                            >> <annoying pedant>
                            >> What, even on a system with CHAR_BIT==16 and sizeof(int)==1 ?
                            >> </annoying pedant>
                            >>
                            >> Of course, you are only likely to find such systems in the embedded world
                            >> where you may well not have printf.
                            >>[/color]
                            > But often you have vsprintf(), or you need to implement it.
                            >
                            > The whole language does begin to break down when we push the limits of
                            > ANSI's definition. For instance, should field-length parameters really be
                            > size_t s?[/color]

                            You could take the cheap way out and do stuff along the lines of

                            sprintf(format, "%%%d.%df",widt h,precision>=0? precision:0);

                            c89 doesn't appear to provide for field-length parameters anyway - at
                            least the draft i have doesn't.

                            Comment

                            • Bliss

                              #15
                              Re: Printf question.



                              praeiji dropped $.02 in the slot and wrote:[color=blue]
                              > Hi,
                              >
                              > I was wondering something today. The following code :
                              >
                              > unsigned char a = 200;
                              > char b = 200;
                              > printf( "%d %d", a, b );
                              >
                              > gives :
                              >
                              > 200, -56
                              >
                              > How comes? I didn't tell printf that the first argument was unsigned
                              > and it detected it on its own. It doesn't seem possible with varargs.
                              > How is it possible?[/color]

                              That would happen if plain char on your machine is signed and char is
                              eight bits wide. The assignment b = 200 makes b -56.

                              Roger.


                              Comment

                              Working...