Variable Argument Functions

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

    #1

    Variable Argument Functions

    i have statements
    printf("%f",(do uble)1); /* works fine although i have sent %f for
    double */
    printf("%c",(in t)64); /* works fine although i have sent %c for
    int */

    Need your comment on this.

    As my understanding, when we pass something on variable argument, its
    type will be promoted . char is promoted to Int . float is promoted to
    double . that is why above things work fine.

    let me know your comments on above statements. we can extends this talk
    for signed and unsigned , and long double.

  • Papastefanos Serafeim

    #2
    Re: Variable Argument Functions

    ? "shaanxxx" <shaanxxx@yahoo .com?????? ??? ??????
    news:1156927389 .757045.147580@ p79g2000cwp.goo glegroups.com.. .
    i have statements
    printf("%f",(do uble)1); /* works fine although i have sent %f for
    double */
    printf("%c",(in t)64); /* works fine although i have sent %c for
    int */
    >
    Need your comment on this.
    >
    As my understanding, when we pass something on variable argument, its
    type will be promoted . char is promoted to Int . float is promoted to
    double . that is why above things work fine.
    >
    let me know your comments on above statements. we can extends this talk
    for signed and unsigned , and long double.
    >
    Actually nothing is promoted.
    printf("%c",(in t)64)
    works fine, because the first 8 bits of an int and a char are the same. But
    that's not always the case.

    The compiler doesn't have any way to know the types of the parameters
    you pass on a function receiving a variable number of args, so no
    promotion is possible.

    --
    Papastefanos Serafeim


    Comment

    • Richard Heathfield

      #3
      Re: Variable Argument Functions

      Papastefanos Serafeim said:
      ? "shaanxxx" <shaanxxx@yahoo .com?????? ??? ??????
      news:1156927389 .757045.147580@ p79g2000cwp.goo glegroups.com.. .
      >i have statements
      >printf("%f",(d ouble)1); /* works fine although i have sent %f for
      >double */
      >printf("%c",(i nt)64); /* works fine although i have sent %c for
      >int */
      >>
      >Need your comment on this.
      >>
      >As my understanding, when we pass something on variable argument, its
      >type will be promoted . char is promoted to Int . float is promoted to
      >double . that is why above things work fine.
      >>
      >let me know your comments on above statements. we can extends this talk
      >for signed and unsigned , and long double.
      >>
      >
      Actually nothing is promoted.
      printf("%c",(in t)64)
      works fine, because the first 8 bits of an int and a char are the same.
      It does work fine, but that isn't the reason, as on some systems the first 8
      bits of an int and a char are /not/ the same!

      The reason it works fine is that 64 is already an int, so there is no
      particular problem in converting it to one.

      This works fine too:

      char c = 'A'; /* 'A' is an int, but c is a char */
      printf("%c\n", c);

      c is a char, but the compiler will convert its value to int type before
      passing that value to printf, which expects an int to match the %c
      specifier.

      As the Standard points out:

      c The int argument is converted to an unsigned char , and the resulting
      character is written.

      Note: "The int argument"!

      But that's not always the case.
      >
      The compiler doesn't have any way to know the types of the parameters
      you pass on a function receiving a variable number of args, so no
      promotion is possible.
      [Nit: You pass arguments, not parameters, and the function receives
      parameters, not arguments.]

      The default argument promotions do in fact occur. See 4.8.1.2 in C89:

      "The va_arg macro expands to an expression that has the type and
      value of the next argument in the call. The parameter ap shall be the
      same as the va_list ap initialized by va_start . Each invocation of
      va_arg modifies ap so that the values of successive arguments are
      returned in turn. The parameter type is a type name specified such
      that the type of a pointer to an object that has the specified type
      can be obtained simply by postfixing a * to type . If there is no
      actual next argument, or if type is not compatible with the type of
      the actual next argument (as promoted according to the default
      argument promotions), the behavior is undefined."

      --
      Richard Heathfield
      "Usenet is a strange place" - dmr 29/7/1999

      email: rjh at above domain (but drop the www, obviously)

      Comment

      • Harald van Dijk

        #4
        Re: Variable Argument Functions

        Papastefanos Serafeim wrote:
        ? "shaanxxx" <shaanxxx@yahoo .com?????? ??? ??????
        news:1156927389 .757045.147580@ p79g2000cwp.goo glegroups.com.. .
        i have statements
        printf("%f",(do uble)1); /* works fine although i have sent %f for
        double */
        printf("%c",(in t)64); /* works fine although i have sent %c for
        int */

        Need your comment on this.

        As my understanding, when we pass something on variable argument, its
        type will be promoted . char is promoted to Int . float is promoted to
        double . that is why above things work fine.
        Correct. In fact, %f and %c are documented as accepting types double
        and int, respectively, not float and (unsigned) char. It's only because
        of the promotions that it will work with float and char. In fact,
        ignoring the possibility of overflow, the below code is valid and
        equivalent to printing "A\n":

        printf("%c\n", 'A' + UCHAR_MAX + 1);
        let me know your comments on above statements. we can extends this talk
        for signed and unsigned , and long double.
        >
        Actually nothing is promoted.
        printf("%c",(in t)64)
        works fine, because the first 8 bits of an int and a char are the same. But
        that's not always the case.
        It will work fine on any conforming C implementation, as long as it
        provides the standard I/O functions, and as long as 64 is a printable
        character.
        The compiler doesn't have any way to know the types of the parameters
        you pass on a function receiving a variable number of args, so no
        promotion is possible.
        The logic is sane enough, but the conclusion should be a bit different:
        promotion is done regardless of the format string.

        Comment

        • shaanxxx

          #5
          Re: Variable Argument Functions


          Papastefanos Serafeim wrote:
          ? "shaanxxx" <shaanxxx@yahoo .com?????? ??? ??????
          news:1156927389 .757045.147580@ p79g2000cwp.goo glegroups.com.. .
          i have statements
          printf("%f",(do uble)1); /* works fine although i have sent %f for
          double */
          printf("%c",(in t)64); /* works fine although i have sent %c for
          int */

          Need your comment on this.

          As my understanding, when we pass something on variable argument, its
          type will be promoted . char is promoted to Int . float is promoted to
          double . that is why above things work fine.

          let me know your comments on above statements. we can extends this talk
          for signed and unsigned , and long double.
          >
          Actually nothing is promoted.
          printf("%c",(in t)64)
          works fine, because the first 8 bits of an int and a char are the same. But
          that's not always the case.
          >
          The compiler doesn't have any way to know the types of the parameters
          you pass on a function receiving a variable number of args, so no
          promotion is possible.
          >
          --
          Papastefanos Serafeim
          #include <stdarg.h>

          /* minprintf: minimal printf with variable argument list */
          void minprintf(char *fmt, ...)
          {
          va_list ap; /* points to each unnamed arg in turn */
          char *p, *sval;
          int ival;
          double dval;

          va_start(ap, fmt); /* make ap point to 1st unnamed arg */
          for (p = fmt; *p; p++) {
          if (*p != '%') {
          putchar(*p);
          continue;
          }
          switch (*++p) {
          case 'd':
          ival = va_arg(ap, int);
          printf("%d", ival);
          break;
          case 'f':
          dval = va_arg(ap, double);
          printf("%f", dval);
          break;
          case 's':
          for (sval = va_arg(ap, char *); *sval; sval++)
          putchar(*sval);
          break;
          default:
          putchar(*p);
          break;
          }
          }
          va_end(ap); /* clean up when done */
          }

          above code is taken from "The C programming Language"
          By Brian W. Kernighan and Dennis M. Ritchie.

          look at case float case, author have used double for the case of float.
          If we change following code

          case 'f':
          dval = va_arg(ap, double);
          printf("%f", dval);
          break;


          to

          case 'f':
          dval = va_arg(ap, float);
          printf("%f", dval);
          break;

          It will not work for float since float is alway passed as double on
          argument (stack : non standard word ).

          I tested on windows compiler , it didnt work.

          Comment

          • Dave Thompson

            #6
            Re: Variable Argument Functions

            On Wed, 30 Aug 2006 10:12:51 +0000, Richard Heathfield
            <invalid@invali d.invalidwrote:
            Papastefanos Serafeim said:
            <snip printf case, with correct response of %c taking int argument>
            But that's not always the case.

            The compiler doesn't have any way to know the types of the parameters
            you pass on a function receiving a variable number of args, so no
            promotion is possible.
            >
            [Nit: You pass arguments, not parameters, and the function receives
            parameters, not arguments.]
            >
            The default argument promotions do in fact occur. See 4.8.1.2 in C89:
            <snipped>
            But that's only an aside, plus it's not clear that variadic std-lib
            routines *printf and *scanf must actually use va_arg and friends.
            (Plus that specific document is now rather difficult to get.)

            The directly applicable statement is in C90 6.3.2.2 or C99 6.5.2.2p7:
            "... The ellipsis notation in a function prototype declarator causes
            argument type conversion to stop after the last declared parameter.
            The default argument promotions are performed on trailing arguments."

            I would add: since as far as the standard is concerned there is only
            one implementation at a time and thus the same compiler is responsible
            for both caller and callee sides, it actually _could_ implement a
            scheme that identifies (and checks) types. But there is no standard
            requirement to do so, nor portable way to access it; and thus
            programmers habituated to its absence don't even ask for it, and
            implementors seeing no demand and nontrivial cost don't provide it.
            <evil smirkHey, Jacob, come over here a moment ... </>

            - David.Thompson1 at worldnet.att.ne t

            Comment

            Working...