Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

does varargs offer a kind of poor man's polymorphism?

31 views
Skip to first unread message

pete

unread,
Dec 16, 2010, 8:58:07 PM12/16/10
to

No doubt every other student of C has noticed this; it's new to me.

If I declare:

int xlate( void *, ... );

and then define xlate( ) in several different ways (maybe all
definitions but one are #ifdef-ed out):

int xlate ( char *arg1 ) { ... }
int xlate ( int arg1, char *arg2, int arg3 ) { ... }
int xlate ( char arg1, int *arg2 ) { ... }

and omit any mention of va_list -- never mentioning it -- in every
definition of xlate( ); and then call xlate( ) abiding by one of its
several definitions, it seems that every compiled version of xlate( )
works just the way I want, at least under gcc and msvc.

Is this relaxed, undemanding, generous compiler behavior guaranteed
under C99?

Thanks!

-- Pete

Seebs

unread,
Dec 16, 2010, 9:35:07 PM12/16/10
to
On 2010-12-17, pete <pet...@yahoo.com> wrote:
> Is this relaxed, undemanding, generous compiler behavior guaranteed
> under C99?

No, and there's been many counterexamples on real-world architectures.

Don't do that.

-s
--
Copyright 2010, all wrongs reversed. Peter Seebach / usenet...@seebs.net
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
I am not speaking for my employer, although they do rent some of my opinions.

pete

unread,
Dec 16, 2010, 10:19:12 PM12/16/10
to
On Dec 16, 9:35 pm, Seebs <usenet-nos...@seebs.net> wrote:

> On 2010-12-17, pete <pete...@yahoo.com> wrote:
>
> > Is this relaxed, undemanding, generous compiler behavior guaranteed
> > under C99?
>
> No, and there's been many counterexamples on real-world architectures.
>
> Don't do that.
>
> -s
> --
> Copyright 2010, all wrongs reversed.  Peter Seebach / usenet-nos...@seebs.nethttp://www.seebs.net/log/<-- lawsuits, religion, and funny pictureshttp://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!

> I am not speaking for my employer, although they do rent some of my opinions.

Peter, if it's convenient, would you please be good enough to point me
to just any random one of these many counterexamples?

Thanks so much!

-- p

Eric Sosman

unread,
Dec 16, 2010, 10:25:38 PM12/16/10
to
On 12/16/2010 8:58 PM, pete wrote:
>
> No doubt every other student of C has noticed this; it's new to me.
>
> If I declare:
>
> int xlate( void *, ... );
>
> and then define xlate( ) in several different ways (maybe all
> definitions but one are #ifdef-ed out):
>
> int xlate ( char *arg1 ) { ... }
> int xlate ( int arg1, char *arg2, int arg3 ) { ... }
> int xlate ( char arg1, int *arg2 ) { ... }

Each of the three would have to be in a separate compilation unit,
and at least two would have to be `static', and none of the three
compilation units could "see" the declaration. In other words,

1) In a single compilation unit, a name can be defined at most
once.

2) In a single program, a name with external linkage can refer
to only one function, hence one function definition.

3) In a single compilation unit, all declarations and definitions
of a function must agree.

> and omit any mention of va_list -- never mentioning it -- in every
> definition of xlate( ); and then call xlate( ) abiding by one of its
> several definitions, it seems that every compiled version of xlate( )
> works just the way I want, at least under gcc and msvc.

... whatever "works just the way I want" may mean.

> Is this relaxed, undemanding, generous compiler behavior guaranteed
> under C99?

You haven't described "works just the way I want," so the question
is not well-formed. Even so, I'll venture an answer: NO. I'll also
give the C90 answer: NO. And I'll make a guess at the C1x answer: NO.
What part of "NO" are you having trouble understanding? (And, out of
curiosity, why do you use "polymorphism" to describe what most people
term either "overloading" or "Haddocks' Eyes?")

--
Eric Sosman
eso...@ieee-dot-org.invalid

luser- -droog

unread,
Dec 16, 2010, 10:49:15 PM12/16/10
to
On Dec 16, 9:25 pm, Eric Sosman <esos...@ieee-dot-org.invalid> wrote:
> (And, out of
> curiosity, why do you use "polymorphism" to describe what most people
> term either "overloading" or "Haddocks' Eyes?")

Yeah. You can't do polymorphism in C (or function dispatch based on
types) without some non-standard extension like gs's typeof,
or maybe with user-defined tag-unions.

BTW, what's "Haddocks' Eyes"? It sounds so tantalizingly mysterious!

Message has been deleted
Message has been deleted

Eric Sosman

unread,
Dec 17, 2010, 12:11:54 AM12/17/10
to
On 12/16/2010 10:49 PM, luser- -droog wrote:
> On Dec 16, 9:25 pm, Eric Sosman<esos...@ieee-dot-org.invalid> wrote:
>> (And, out of
>> curiosity, why do you use "polymorphism" to describe what most people
>> term either "overloading" or "Haddocks' Eyes?")
>
> Yeah. You can't do polymorphism in C (or function dispatch based on
> types) without some non-standard extension like gs's typeof,
> or maybe with user-defined tag-unions.

The former is non-standard, but the latter need not be.

> BTW, what's "Haddocks' Eyes"? It sounds so tantalizingly mysterious!

GIYF.

--
Eric Sosman
eso...@ieee-dot-org.invalid

Eric Sosman

unread,
Dec 17, 2010, 12:48:34 AM12/17/10
to
On 12/16/2010 11:32 PM, Ered China Luin wrote:
> [...]
> You can pass any type through a var-args call, but get the arguments with va_arg
> and don't lie about the type.

Note that va_arg() must specify the *promoted* type: `double' and
`int' instead of `float' and `short', for example. This makes trouble
with types whose promotion rules differ from one system to another.
For example, in

enum TriplePlay { TINKER, EVERS, CHANCE } infielder = CHANCE;
void func(const char *, ...);
func ("What is the type of the second parameter?", infielder);

The type of the second *argument* is `enum TriplePlay', which we know
is "compatible with char, a signed integer type, or an unsigned integer
type," at the implementation's discretion. The compatible type the
implementation chooses may (or may not be) subject to promotion, and if
promotable may promote to pretty much anything. So, what type should
the va_arg() macro use to retrieve the second parameter? Different
implementations will give different answers (and `enum TriplePlay' will
not be among them, if that is a promotable type).

Even `size_t' and `ptrdiff_t' are theoretically subject to this
problem, although in practice they are usually wide enough that they
do not promote. Still, it is possible for a Standard-conforming C to
have `SIZE_MAX < INT_MAX', and if this happens a `size_t' argument
will promote to an `int' parameter and `va_arg(ap, size_t)' will be
incorrect.

For ultimate safety in passing (possibly) promotable types to
varargs functions, I guess you could wrap the suspect value in a
struct or union, types that are never promoted:

union Wrapper { enum TriplePlay payload; } carrier;
carrier.payload = infielder;
func ("The second parameter is a `union Wrapper'.", carrier);

Another possibility is to pass a pointer:

func ("The second parameter points to an `enum TriplePlay'.",
&infielder);

I confess, though, that I've never seen these dodges used -- not even
by people who've previously fallen afoul of an unexpected promotion!

--
Eric Sosman
eso...@ieee-dot-org.invalid

Message has been deleted

Seebs

unread,
Dec 17, 2010, 1:00:34 AM12/17/10
to
On 2010-12-17, pete <pet...@yahoo.com> wrote:
> Peter, if it's convenient, would you please be good enough to point me
> to just any random one of these many counterexamples?

Don't remember which systems, but there are systems where variadic
functions have all arguments passed on the stack, but other functions
typically use registers for at least some arguments, such as floating
point values.

-s
--
Copyright 2010, all wrongs reversed. Peter Seebach / usenet...@seebs.net

pete

unread,
Dec 17, 2010, 6:19:28 AM12/17/10
to
Thanks, everyone. I appreciate all the comments and course
corrections.

-- pete
----------
"it means just what I choose it to mean -- neither more nor less"
-- Humpty Dumpty

christian.bau

unread,
Dec 17, 2010, 7:45:26 AM12/17/10
to
On Dec 17, 3:19 am, pete <pete...@yahoo.com> wrote:

> Peter, if it's convenient, would you please be good enough to point me
> to just any random one of these many counterexamples?

gcc and other compilers for PowerPC.

David Thompson

unread,
Dec 27, 2010, 5:41:32 AM12/27/10
to
On Fri, 17 Dec 2010 00:48:34 -0500, Eric Sosman
<eso...@ieee-dot-org.invalid> wrote:

> On 12/16/2010 11:32 PM, Ered China Luin wrote:
> > [...]
> > You can pass any type through a var-args call, but get the arguments with va_arg
> > and don't lie about the type.
>
> Note that va_arg() must specify the *promoted* type: `double' and
> `int' instead of `float' and `short', for example. This makes trouble
> with types whose promotion rules differ from one system to another.

> For example, [enum which may be (compatible with) any integer type]


> at the implementation's discretion. The compatible type the
> implementation chooses may (or may not be) subject to promotion, and if
> promotable may promote to pretty much anything. So, what type should

In principle, but enums in C can never exceed the range of 'int',
which is also normatively (though ill-definedly) 'the natural size'
for the execution environment, so I see no good reason ever to use
anything wider. An implementation can reasonably narrower integers,
but they are all taken to int by the default promotions. Have you seen
actual problems here?

> the va_arg() macro use to retrieve the second parameter? Different
> implementations will give different answers (and `enum TriplePlay' will
> not be among them, if that is a promotable type).
>
> Even `size_t' and `ptrdiff_t' are theoretically subject to this
> problem, although in practice they are usually wide enough that they
> do not promote. Still, it is possible for a Standard-conforming C to
> have `SIZE_MAX < INT_MAX', and if this happens a `size_t' argument
> will promote to an `int' parameter and `va_arg(ap, size_t)' will be
> incorrect.
>

Yeah, that one is usually okay but could be a problem.

Similarly but without vararg, getting socklen_t to port right has
wasted more of my time than can be justified in any sane universe.

<snip rest>

Malcolm McLean

unread,
Dec 27, 2010, 9:13:47 AM12/27/10
to
On Dec 17, 5:48 am, Eric Sosman <esos...@ieee-dot-org.invalid> wrote:
>
>         func ("The second parameter points to an `enum TriplePlay'.",
>               &infielder);
>
> I confess, though, that I've never seen these dodges used -- not even
> by people who've previously fallen afoul of an unexpected promotion!
>
>
In high-level languages you often see this

answer = power(base = x, exponent = y)

it means that caller can miss out parameters, and doesn't have to
remember the order in which arguments are passed. It also gives a
powerful clue to the reader what they mean.
You can do the same with C varags, but I must confess I've never see
it done.

Mark Wooding

unread,
Dec 27, 2010, 12:09:12 PM12/27/10
to
Malcolm McLean <malcolm...@btinternet.com> writes:

> In high-level languages you often see this
>
> answer = power(base = x, exponent = y)
>

> You can do the same with C varags, but I must confess I've never see
> it done.

The X Toolkit Intrinsics (Xt) library does something rather like this,
e.g., in XtVaCreateWidget. The Gobject system also has something
similar, in g_object_new and friends.

-- [mdw]

Stephen Sprunk

unread,
Dec 27, 2010, 3:06:06 PM12/27/10
to

No; this invokes undefined behavior. One possible result of undefined
behavior may be doing exactly what you want--until it comes time to port
to another implementation or demo your "working" code to your boss/customer.

There exist implementations which pass arguments to variadic functions
on the stack but arguments to non-variadic functions in registers, which
is allowed by the Standard but will obviously break your code.

S

--
Stephen Sprunk "God does not play dice." --Albert Einstein
CCIE #3723 "God is an inveterate gambler, and He throws the
K5SSS dice at every possible opportunity." --Stephen Hawking

0 new messages