va_arg and short

Discussion in 'C Programming' started by Glen Herrmannsfeldt, Nov 2, 2003.

  1. I was compiling a program written by someone else about six years ago, and
    widely distributed at the time. It also includes makefiles for many
    different systems, so I know it has been compiled with many different
    compilers.

    I got compile errors when it used va_arg to fetch an argument of type short.
    That seemed a little strange to me, so I changed it to int and it compiled
    just fine.

    So now I wonder, just what is the rule for va_arg and short? It would seem
    strange to reject certain types, yet that is what the compiler did.

    -- glen
     
    Glen Herrmannsfeldt, Nov 2, 2003
    #1
    1. Advertising

  2. Glen Herrmannsfeldt

    Chris Torek Guest

    In article <aE0pb.81932$HS4.680953@attbi_s01>
    Glen Herrmannsfeldt <> writes:
    >I got compile errors when [some code] used va_arg to fetch an
    >argument of type short. That seemed a little strange to me, so
    >I changed it to int and it compiled just fine.
    >
    >So now I wonder, just what is the rule for va_arg and short?


    It is up to the programmer to avoid passing "narrow" types to the
    va_arg() macro.

    The type name given to va_arg() must match the type of the actual
    parameter, whatever it was. In a call to a function that lacks a
    prototype, or whose prototype ends in ", ..." (where the actual
    argument matches the ", ..." part), the compiler is obligated to
    perform the "default argument promotions". These replace (signed)
    char and short with int, and float with double. They also replace
    unsigned char and unsigned short with some wider type, but the
    wider type is not easily predicted because the ANSI X3J11 committee
    folks chose the wrong rules in 1985 or so. (Plain char will widen
    to signed int on any sensible platform, but even this is not
    guaranteed.)

    Hence, for strict conformance, one might code something like this:

    case 'i': /* obtain an int */
    int_val = va_arg(ap, int);
    ...
    break;

    case 's': /* obtain a (signed) short */
    short_val = (short)va_arg(ap, int);
    ...
    break;

    case 'S': /* obtain an unsigned short */
    #if USHRT_MAX > INT_MAX
    ushort_val = (unsigned short)va_arg(ap, unsigned int);
    #else
    ushort_val = (unsigned short)va_arg(ap, int);
    #endif
    ...
    break;

    Note the icky need for a "#if" test, to tell which type unsigned
    short becomes under the default argument promotions. (Had C used
    the "predictably surprising" rule "unsigned promotes to unsigned",
    the #if would not be required. Of course, this rule would also
    have to go with one that says that if plain char is unsigned, it
    widens to signed int anyway, possibly with a secondary requirement
    for UCHAR_MAX to be no greater than INT_MAX on any such system.
    This would not have been a hardship for existing implementations,
    and the resulting rules are far easier to work with and do not
    change from one implementation to another the way the current ones
    do.)

    >It would seem strange to reject certain types, yet that is what
    >the compiler did.


    A C compiler is not required to detect and reject such usage -- it
    falls under the broad umbrella of undefined behavior -- but a kind
    and clever compiler will do it. :)
    --
    In-Real-Life: Chris Torek, Wind River Systems
    Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
    email: forget about it http://67.40.109.61/torek/index.html (for the moment)
    Reading email is like searching for food in the garbage, thanks to spammers.
     
    Chris Torek, Nov 2, 2003
    #2
    1. Advertising

  3. Glen Herrmannsfeldt

    James Hu Guest

    On 2003-11-02, Glen Herrmannsfeldt <> wrote:
    > I was compiling a program written by someone else about six years ago, and
    > widely distributed at the time. It also includes makefiles for many
    > different systems, so I know it has been compiled with many different
    > compilers.
    >
    > I got compile errors when it used va_arg to fetch an argument of type short.
    > That seemed a little strange to me, so I changed it to int and it compiled
    > just fine.
    >
    > So now I wonder, just what is the rule for va_arg and short? It would seem
    > strange to reject certain types, yet that is what the compiler did.


    C99: 6.3.1.1, paragraph 2

    "If an int can represent all the values of the original type, the
    value is converted to an int; otherwise, it is converted to an
    unsigned int. These are called the /integer promotions/."

    C99: 6.5.2.2, paragraph 6

    "If the expression that denotes the called function has a type that
    does not include a prototype, the integer promotions are performed
    on each argument, and arguments that have type float are promoted
    to double. These are called the /default argument promotions/.

    C99: 6.5.2.2, paragraph 7

    "The ellipses 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."


    -- James
     
    James Hu, Nov 2, 2003
    #3
  4. "Chris Torek" <> wrote in message
    news:bo27at$10g$...
    > In article <aE0pb.81932$HS4.680953@attbi_s01>
    > Glen Herrmannsfeldt <> writes:
    > >I got compile errors when [some code] used va_arg to fetch an
    > >argument of type short. That seemed a little strange to me, so
    > >I changed it to int and it compiled just fine.
    > >
    > >So now I wonder, just what is the rule for va_arg and short?

    >
    > It is up to the programmer to avoid passing "narrow" types to the
    > va_arg() macro.
    >
    > The type name given to va_arg() must match the type of the actual
    > parameter, whatever it was. In a call to a function that lacks a
    > prototype, or whose prototype ends in ", ..." (where the actual
    > argument matches the ", ..." part), the compiler is obligated to
    > perform the "default argument promotions". These replace (signed)
    > char and short with int, and float with double. They also replace
    > unsigned char and unsigned short with some wider type, but the
    > wider type is not easily predicted because the ANSI X3J11 committee
    > folks chose the wrong rules in 1985 or so. (Plain char will widen
    > to signed int on any sensible platform, but even this is not
    > guaranteed.)


    I knew about the default promotions, so it wasn't hard to know what to
    change it to. The program was so widely distributed, and run on so many
    different compilers, I was surprised that it hadn't been seen before. Now,
    most likely it is never executed. It is a modified version of sprintf(),
    and if the h flag is used it will print a short. I don't know anyone that
    ever did that, though they may have been surprised if they did.

    (snip)

    > A C compiler is not required to detect and reject such usage -- it
    > falls under the broad umbrella of undefined behavior -- but a kind
    > and clever compiler will do it. :)


    Apparently compilers have gotten kinder and cleverer in recent years.

    -- glen
     
    Glen Herrmannsfeldt, Nov 2, 2003
    #4
  5. In article <aE0pb.81932$HS4.680953@attbi_s01>,
    "Glen Herrmannsfeldt" <> wrote:

    > I was compiling a program written by someone else about six years ago, and
    > widely distributed at the time. It also includes makefiles for many
    > different systems, so I know it has been compiled with many different
    > compilers.
    >
    > I got compile errors when it used va_arg to fetch an argument of type short.
    > That seemed a little strange to me, so I changed it to int and it compiled
    > just fine.
    >
    > So now I wonder, just what is the rule for va_arg and short? It would seem
    > strange to reject certain types, yet that is what the compiler did.


    When you use the va_arg macro, the type that you supply must (with some
    exceptions that don't apply here) match the type of the actual argument
    _after default promotions_.

    Any argument of type short would be promoted to int, so using short in
    the va_arg macro can never match the type of the actual argument after
    default promotions.
     
    Christian Bau, Nov 2, 2003
    #5
  6. [Cross posted to comp.std.c.]

    "Glen Herrmannsfeldt" <> wrote in message news:<aE0pb.81932$HS4.680953@attbi_s01>...
    > I was compiling a program written by someone else about six years ago, and
    > widely distributed at the time. It also includes makefiles for many
    > different systems, so I know it has been compiled with many different
    > compilers.
    >
    > I got compile errors when it used va_arg to fetch an argument of type short.
    > That seemed a little strange to me, so I changed it to int and it compiled
    > just fine.
    >
    > So now I wonder, just what is the rule for va_arg and short? It would seem
    > strange to reject certain types, yet that is what the compiler did.


    I wonder why va_arg could not accept a type subject to promotion and
    handle them accordingly, i.e. accept the promoted type implicitly and
    convert it to the original/requested type. [So, cases like the
    character types and unsigned short, which might promote to signed or
    unsigned int, could be handled without having to resort to integer
    limit checks.]

    What sorts of architectures would make such an alternative va_arg
    behaviour difficult to implement in practice?

    [I appreciate the status quo is not likely to change, I'm just curious
    as to whether it was considered for C90 or C99, or if not, how the
    Committee might discus the request.]

    --
    Peter
     
    Peter Nilsson, Nov 3, 2003
    #6
  7. >I wonder why va_arg could not accept a type subject to promotion and
    >handle them accordingly, i.e. accept the promoted type implicitly and
    >convert it to the original/requested type. [So, cases like the
    >character types and unsigned short, which might promote to signed or
    >unsigned int, could be handled without having to resort to integer
    >limit checks.]
    >
    >What sorts of architectures would make such an alternative va_arg
    >behaviour difficult to implement in practice?


    If C had type-valued functions, this might be easier to deal with.
    For example,
    type_standard_promotions(typeof(short)) == typeof(int)
    I don't think clever tricks with macros can deal with this without
    also using a magic compiler built-in.

    As it stands, the second argument of va_arg has to be a valid type
    if you append a "*" to it; this restriction wouldn't be necessary
    if you had:
    type_addressof(typeof(int)) == typeof(int *)

    >[I appreciate the status quo is not likely to change, I'm just curious
    >as to whether it was considered for C90 or C99, or if not, how the
    >Committee might discus the request.]


    Gordon L. Burditt
     
    Gordon Burditt, Nov 3, 2003
    #7
  8. In article <>,
    (Peter Nilsson) wrote:

    > [Cross posted to comp.std.c.]
    >
    > "Glen Herrmannsfeldt" <> wrote in message
    > news:<aE0pb.81932$HS4.680953@attbi_s01>...
    > > I was compiling a program written by someone else about six years ago, and
    > > widely distributed at the time. It also includes makefiles for many
    > > different systems, so I know it has been compiled with many different
    > > compilers.
    > >
    > > I got compile errors when it used va_arg to fetch an argument of type
    > > short.
    > > That seemed a little strange to me, so I changed it to int and it compiled
    > > just fine.
    > >
    > > So now I wonder, just what is the rule for va_arg and short? It would
    > > seem
    > > strange to reject certain types, yet that is what the compiler did.

    >
    > I wonder why va_arg could not accept a type subject to promotion and
    > handle them accordingly, i.e. accept the promoted type implicitly and
    > convert it to the original/requested type. [So, cases like the
    > character types and unsigned short, which might promote to signed or
    > unsigned int, could be handled without having to resort to integer
    > limit checks.]


    These are no problem anyway, because the C Standard explicitely allows
    you to use for example unsigned int instead of int if the value passed
    can be represented in both types. So whether unsigned short is passed as
    int or unsigned int, you can always read it as an unsigned int.

    > What sorts of architectures would make such an alternative va_arg
    > behaviour difficult to implement in practice?


    Many implementations implement va_arg as a macro, without requiring any
    special knowledge in the compiler itself. Producing code that works for
    "short" if sizeof (short) < sizeof (int) by using a macro alone is
    difficult. So this requirement would mean you have to change the
    compiler.

    On the other hand, as a compiler writer I would say that the best
    possible result is a compile time error. That way the programmer has a
    chance to change their code. Much better than accepting code that will
    be accepted and lead to a crash on the next machine.
     
    Christian Bau, Nov 3, 2003
    #8
  9. Glen Herrmannsfeldt

    James Kuyper Guest

    (Peter Nilsson) wrote in message news:<>...
    > [Cross posted to comp.std.c.]
    >
    > "Glen Herrmannsfeldt" <> wrote in message news:<aE0pb.81932$HS4.680953@attbi_s01>...
    > > I was compiling a program written by someone else about six years ago, and
    > > widely distributed at the time. It also includes makefiles for many
    > > different systems, so I know it has been compiled with many different
    > > compilers.
    > >
    > > I got compile errors when it used va_arg to fetch an argument of type short.
    > > That seemed a little strange to me, so I changed it to int and it compiled
    > > just fine.
    > >
    > > So now I wonder, just what is the rule for va_arg and short? It would seem
    > > strange to reject certain types, yet that is what the compiler did.

    >
    > I wonder why va_arg could not accept a type subject to promotion and
    > handle them accordingly, i.e. accept the promoted type implicitly and
    > convert it to the original/requested type. [So, cases like the
    > character types and unsigned short, which might promote to signed or
    > unsigned int, could be handled without having to resort to integer
    > limit checks.]
    >
    > What sorts of architectures would make such an alternative va_arg
    > behaviour difficult to implement in practice?


    The normal va_arg() macro can, on many platforms, expand to normal C
    code. On some platforms, something like the following is sufficient:

    typedef char* va_list;
    #define va_start(arg) )(&arg+sizeof(arg))
    #define va_arg(ap,type) ((type*)(ap+=sizeof(type)))[-1]
    #define va_end(ap)

    Try to figure out how to modify that without using any extensions to C
    such as sizeof(promoted_typeof(type)). An implementation is free, of
    course, to use extensions, but I think that the committee would resist
    changing the specification in a way that would make the use of an
    extension mandatory.
     
    James Kuyper, Nov 3, 2003
    #9
  10. Glen Herrmannsfeldt

    James Kuyper Guest

    Christian Bau <> wrote in message news:<>...
    ....
    > Many implementations implement va_arg as a macro, ...


    I should hope so! The standard requires that it be a macro.
     
    James Kuyper, Nov 3, 2003
    #10
  11. Glen Herrmannsfeldt

    Thad Smith Guest

    Peter Nilsson wrote:

    > I wonder why va_arg could not accept a type subject to promotion and
    > handle them accordingly, i.e. accept the promoted type implicitly and
    > convert it to the original/requested type. [So, cases like the
    > character types and unsigned short, which might promote to signed or
    > unsigned int, could be handled without having to resort to integer
    > limit checks.]


    While the programmer should know that the type char and short are
    promoted, what about int32_t? Can it be an argument of va_arg? It
    might be equivalent to a short (needing promotion), or a int or a long.
    Is there any way of portably accessing a variadic int32_t (or intX_t for
    X >= 16) parameter?

    Thad
     
    Thad Smith, Nov 3, 2003
    #11
  12. Glen Herrmannsfeldt

    Dan Pop Guest

    In <aE0pb.81932$HS4.680953@attbi_s01> "Glen Herrmannsfeldt" <> writes:

    >I was compiling a program written by someone else about six years ago, and
    >widely distributed at the time. It also includes makefiles for many
    >different systems, so I know it has been compiled with many different
    >compilers.
    >
    >I got compile errors when it used va_arg to fetch an argument of type short.
    >That seemed a little strange to me, so I changed it to int and it compiled
    >just fine.
    >
    >So now I wonder, just what is the rule for va_arg and short? It would seem
    >strange to reject certain types, yet that is what the compiler did.


    It's a clear case of undefined behaviour:

    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.
    ====================^^^^^^^^^^^^^^^^^^^^^^^^^^^

    A short argument is promoted to int, therefore, by specifying short as the
    type you're guaranteed to have a type mismatch, leading to undefined
    behaviour. The compiler that rejected it just did you a favour. The code
    was written by an incompetent programmer.

    Dan
    --
    Dan Pop
    DESY Zeuthen, RZ group
    Email:
     
    Dan Pop, Nov 3, 2003
    #12
  13. "Dan Pop" <> wrote in message
    news:bo64s4$dkd$...
    > In <aE0pb.81932$HS4.680953@attbi_s01> "Glen Herrmannsfeldt"

    <> writes:
    >
    > >I was compiling a program written by someone else about six years ago,

    and
    > >widely distributed at the time. It also includes makefiles for many
    > >different systems, so I know it has been compiled with many different
    > >compilers.
    > >
    > >I got compile errors when it used va_arg to fetch an argument of type

    short.
    > >That seemed a little strange to me, so I changed it to int and it

    compiled
    > >just fine.


    (snip)

    > A short argument is promoted to int, therefore, by specifying short as the
    > type you're guaranteed to have a type mismatch, leading to undefined
    > behaviour. The compiler that rejected it just did you a favour. The code
    > was written by an incompetent programmer.


    I don't disagree with that. This program is part of a widely distributed
    program library, and I am sure has been compiled on many compilers over the
    years. Most likely, this statement has never been executed, so it really
    doesn't matter what it compiles into. The problem comes when a program is
    supposed to be portable to a wide variety of machines and compilers, with
    the expectation that it can be compiled and installed by non-C programmers.
    Someone is supposed to be able to untar it, run make, and not have any
    compiler or link errors. Considering that it passed so many compilers on
    the way, would it have been reasonable to make it a warning?

    The next error I ran into, in a different library, came from not finding the
    include file ndbm.h. It seems that it is now db.h, at least on the system
    that I was using.

    Oh well.

    -- glen
     
    Glen Herrmannsfeldt, Nov 4, 2003
    #13
  14. (James Kuyper) wrote in message news:<>...
    > (Peter Nilsson) wrote in message news:<>...
    > > [Cross posted to comp.std.c.]
    > >
    > > "Glen Herrmannsfeldt" <> wrote in message news:<aE0pb.81932$HS4.680953@attbi_s01>...
    > > > I was compiling a program written by someone else about six years ago, and
    > > > widely distributed at the time. It also includes makefiles for many
    > > > different systems, so I know it has been compiled with many different
    > > > compilers.
    > > >
    > > > I got compile errors when it used va_arg to fetch an argument of type
    > > > short. That seemed a little strange to me, so I changed it to int and it
    > > > compiled just fine.
    > > >
    > > > So now I wonder, just what is the rule for va_arg and short? It would
    > > > seem strange to reject certain types, yet that is what the compiler did.

    > >
    > > I wonder why va_arg could not accept a type subject to promotion and
    > > handle them accordingly, i.e. accept the promoted type implicitly and
    > > convert it to the original/requested type. [So, cases like the
    > > character types and unsigned short, which might promote to signed or
    > > unsigned int, could be handled without having to resort to integer
    > > limit checks.]
    > >
    > > What sorts of architectures would make such an alternative va_arg
    > > behaviour difficult to implement in practice?

    >
    > The normal va_arg() macro can, on many platforms, expand to normal C
    > code. On some platforms, something like the following is sufficient:
    >
    > typedef char* va_list;
    > #define va_start(arg) )(&arg+sizeof(arg))


    #define va_start(ap,arg) ((ap) = (char *) &arg) /* ? */

    > #define va_arg(ap,type) ((type*)(ap+=sizeof(type)))[-1]
    > #define va_end(ap)
    >
    > Try to figure out how to modify that without using any extensions to C
    > such as sizeof(promoted_typeof(type)). An implementation is free, of
    > course, to use extensions, but I think that the committee would resist
    > changing the specification in a way that would make the use of an
    > extension mandatory.


    The 'extension' is static type analysis, indeed, the *same* analysis
    used to promote parameters in variadic function calls in the first
    place.

    --
    Peter
     
    Peter Nilsson, Nov 4, 2003
    #14
  15. Thad Smith <> wrote in message news:<>...
    > Peter Nilsson wrote:
    >
    > > I wonder why va_arg could not accept a type subject to promotion and
    > > handle them accordingly, i.e. accept the promoted type implicitly and
    > > convert it to the original/requested type. [So, cases like the
    > > character types and unsigned short, which might promote to signed or
    > > unsigned int, could be handled without having to resort to integer
    > > limit checks.]

    >
    > While the programmer should know that the type char and short are
    > promoted, what about int32_t? Can it be an argument of va_arg? It
    > might be equivalent to a short (needing promotion), or a int or a long.
    > Is there any way of portably accessing a variadic int32_t (or intX_t for
    > X >= 16) parameter?


    A tedious one...

    #if INT32_MAX <= INT_MAX
    int32_t x = va_arg(ap, int);
    #else
    int32_t x = va_arg(ap, int32_t);
    #endif

    --
    Peter
     
    Peter Nilsson, Nov 4, 2003
    #15
  16. Glen Herrmannsfeldt

    Chris Torek Guest

    > (James Kuyper) wrote in message news:<>...
    >> The normal va_arg() macro can, on many platforms, expand to normal C
    >> code. On some platforms, something like the following is sufficient:
    >>
    >> typedef char* va_list;
    >> #define va_start(arg) )(&arg+sizeof(arg))


    In article <>
    Peter Nilsson <> writes:
    > #define va_start(ap,arg) ((ap) = (char *) &arg) /* ? */


    No -- the idea is to take the address of the "variable" named "..."
    in something like:

    void f(const char *fmt, ...) {
    va_list ap;

    va_start(ap, fmt);
    /* code here */
    va_end(ap);
    }

    >> #define va_arg(ap,type) ((type*)(ap+=sizeof(type)))[-1]
    >> #define va_end(ap)
    >>
    >> Try to figure out how to modify that without using any extensions to C
    >> such as sizeof(promoted_typeof(type)). ...


    >The 'extension' is static type analysis, indeed, the *same* analysis
    >used to promote parameters in variadic function calls in the first
    >place.


    Yes, but while this is available to the compiler (internally),
    there is no existing C construct that requires that it be exposed
    to the programmer. A __sizeof_promoted_type operator *ought* to
    be trivial to add (because the compiler has to know how to do this
    inside), but it does have to be added. (It is slightly worse than
    this; see the end of this article.)

    All that said, back in 1989, the X3J11 committee actually changed
    the way one used what was then <varargs.h>, adding some required
    explicit syntax -- the ", ..." part of a prototype -- and changing
    the va_start() macro so that it takes two arguments instead of one.
    Having done that, I always thought it was silly not to go the rest
    of the way, and make "..." act like a special purpose variable:

    #define va_start(ap) ((ap) = &...)

    While va_start() could be retained (from <varargs.h> in the new
    <stdarg.h>), the C committee could have written that this is the
    one and only correct way to #define it. The "variable" named ...
    would thus become a non-modifiable, indescribably-typed lvalue
    whose only allowed operation is "take its address", producing a
    value of whatever type "va_list" is.

    Note that this -- removing the second argument to va_start() --
    neatly expresses the constraint C imposes, that there only be a
    single set of varying arguments. Having that second argument
    implies (inappropriately) that one might be able to start the
    varying portion at different points. Furthermore, with this "&..."
    change, the requirement for at least one fixed argument could also
    be dropped, giving us the syntax:

    void g(...) {
    va_list ap;

    ap = &...; /* inline expansion of va_start(ap) */
    /* code here */
    va_end(ap);
    }

    This kind of function makes sense in some contexts, e.g., when
    the body is something like:

    char *p, *ret;
    size_t len = 0;

    while ((p = va_arg(ap, char *)) != NULL)
    len += strlen(p);
    va_end(ap);
    ret = malloc(len + 1);
    if (ret != NULL) {
    char *tail = ret;

    va_start(ap);
    while ((p = va_arg(ap, char *)) != NULL) {
    /* can do this in one line with sprintf, but is slow */
    strcpy(tail, p);
    tail += strlen(tail);
    }
    va_end(ap);
    *tail = '\0'; /* in case there are no strings */
    }

    and of course a final "return ret".

    The issue of whether to require promoted types to va_arg() could
    remain separate. Requiring implementations to provide a "size of
    promoted type" keyword, on implementations that use something as
    simple as the va_arg() macro described above, is not much of a
    hardship -- and for implementations that use "secret" compiler
    tricks to access the varying arguments, doing the promotion is
    still not a hardship. I for one think it would be an improvement:
    not necessarily an *important* one, but in some ways, a "good"
    language is one in which all the minor irritants have been removed
    wherever feasible. One of J&W Pascal's original nasty failings
    was the lack of a default case. Yes, you can work around it with
    an "if" in front of the switch/case -- but this is a pesky thorn,
    and there is no reason not to remove it from the lion's foot.

    Assuming we *were* to add a special new keyword or two, here is
    one way might rewrite va_arg:

    /* original:
    va_arg(ap, ty) (((ty *)(ap += sizeof(ty)))[-1])
    new: */
    #define va_arg(ap, ty) ((ty)((__convert_to_ptr_to_promoted(ty, \
    ap += __sizeof_promoted(ty)))[-1]))

    This also removes the pesky thorn that the "type" parameter to
    va_arg be syntactically valid after suffixing with "*". :)
    --
    In-Real-Life: Chris Torek, Wind River Systems
    Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
    email: forget about it http://67.40.109.61/torek/index.html (for the moment)
    Reading email is like searching for food in the garbage, thanks to spammers.
     
    Chris Torek, Nov 4, 2003
    #16
  17. Glen Herrmannsfeldt

    Brian Inglis Guest

    On Mon, 03 Nov 2003 10:17:18 -0700 in comp.std.c, Thad Smith
    <> wrote:

    >Peter Nilsson wrote:
    >
    >> I wonder why va_arg could not accept a type subject to promotion and
    >> handle them accordingly, i.e. accept the promoted type implicitly and
    >> convert it to the original/requested type. [So, cases like the
    >> character types and unsigned short, which might promote to signed or
    >> unsigned int, could be handled without having to resort to integer
    >> limit checks.]

    >
    >While the programmer should know that the type char and short are
    >promoted, what about int32_t? Can it be an argument of va_arg? It
    >might be equivalent to a short (needing promotion), or a int or a long.
    >Is there any way of portably accessing a variadic int32_t (or intX_t for
    >X >= 16) parameter?


    A long is guaranteed to hold at least the same values as an
    int32_t, int and short may not. A short is guaranteed to hold at
    least the same values as an int16_t. A signed char is guaranteed
    to hold at least the same values as an int8_t. There are no other
    guarantees AFAIR.

    Thanks. Take care, Brian Inglis Calgary, Alberta, Canada
    --
    (Brian dot Inglis at SystematicSw dot ab dot ca)
    fake address use address above to reply
     
    Brian Inglis, Nov 4, 2003
    #17
  18. (Peter Nilsson) writes:

    >Thad Smith <> wrote:
    >> Is there any way of portably accessing a variadic int32_t (or intX_t for
    >> X >= 16) parameter?

    >
    >A tedious one...
    >
    > #if INT32_MAX <= INT_MAX
    > int32_t x = va_arg(ap, int);
    > #else
    > int32_t x = va_arg(ap, int32_t);
    > #endif


    Well, if that works, you could do it a little less tediously:

    #define promoted_va_arg(ap, type, max) \
    ((max) <= INT_MAX ? va_arg((ap), int) : va_arg((ap), (type)))

    int32_t x = promoted_va_arg(ap, int32_t, INT32_MAX);

    --
    Fergus Henderson <> | "I have always known that the pursuit
    The University of Melbourne | of excellence is a lethal habit"
    WWW: <http://www.cs.mu.oz.au/~fjh> | -- the last words of T. S. Garp.
     
    Fergus Henderson, Nov 4, 2003
    #18
  19. Glen Herrmannsfeldt

    Dan Pop Guest

    In <> Thad Smith <> writes:

    >Peter Nilsson wrote:
    >
    >> I wonder why va_arg could not accept a type subject to promotion and
    >> handle them accordingly, i.e. accept the promoted type implicitly and
    >> convert it to the original/requested type. [So, cases like the
    >> character types and unsigned short, which might promote to signed or
    >> unsigned int, could be handled without having to resort to integer
    >> limit checks.]

    >
    >While the programmer should know that the type char and short are
    >promoted, what about int32_t? Can it be an argument of va_arg? It
    >might be equivalent to a short (needing promotion), or a int or a long.
    >Is there any way of portably accessing a variadic int32_t (or intX_t for
    >X >= 16) parameter?


    It is precisely this kind of issues that render the typedef'ed "types" a
    lot less useful and easy to use than their fans believe.

    If I multiply two size_t values, do I get undefined behaviour in case of
    overflow or the result modulo SIZE_MAX? It depends on whether size_t is
    subject to the integral promotions or not, an issue the standard is
    not addressing at all.

    Dan
    --
    Dan Pop
    DESY Zeuthen, RZ group
    Email:
     
    Dan Pop, Nov 4, 2003
    #19
  20. Glen Herrmannsfeldt

    Dan Pop Guest

    In <DJCpb.99053$Fm2.81929@attbi_s04> "Glen Herrmannsfeldt" <> writes:

    >I don't disagree with that. This program is part of a widely distributed
    >program library, and I am sure has been compiled on many compilers over the
    >years. Most likely, this statement has never been executed, so it really
    >doesn't matter what it compiles into. The problem comes when a program is
    >supposed to be portable to a wide variety of machines and compilers, with
    >the expectation that it can be compiled and installed by non-C programmers.


    A non-C programmer has no business using a C compiler or building and
    installing C programs. Imagine that the compiler emits a warning
    (something that the person who wrote the code cannot avoid, for *any* C
    compiler). Without knowing C, how can you tell if the problem can be
    safely ignored, or the resulting executable should not be used?

    >Someone is supposed to be able to untar it, run make, and not have any
    >compiler or link errors.


    Even required diagnostics can be produced as "warnings" instead of
    "errors", so the absence of compiler errors means exactly nothing.

    >Considering that it passed so many compilers on
    >the way, would it have been reasonable to make it a warning?


    When the code is obviously broken, an error is much better. Far too many
    people blissfully ignore the warnings...

    >The next error I ran into, in a different library, came from not finding the
    >include file ndbm.h. It seems that it is now db.h, at least on the system
    >that I was using.


    Another argument for having a C programmer building C programs. Similar
    issues arise with -lcurses vs -lncurses at link time. Again obvious for
    the C programmer and totally insurmountable for the non-C programmer.

    Dan
    --
    Dan Pop
    DESY Zeuthen, RZ group
    Email:
     
    Dan Pop, Nov 4, 2003
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. David Geering

    longs, long longs, short short long ints . . . huh?!

    David Geering, Jan 8, 2007, in forum: C Programming
    Replies:
    15
    Views:
    565
    Keith Thompson
    Jan 11, 2007
  2. Replies:
    4
    Views:
    831
    Kaz Kylheku
    Oct 17, 2006
  3. Ioannis Vranos

    unsigned short, short literals

    Ioannis Vranos, Mar 4, 2008, in forum: C Programming
    Replies:
    5
    Views:
    684
    Eric Sosman
    Mar 5, 2008
  4. Replies:
    8
    Views:
    747
    John Reye
    Apr 26, 2012
  5. Andre
    Replies:
    5
    Views:
    542
    Keith Thompson
    Jul 17, 2012
Loading...

Share This Page