Newsgroup: comp.lang.c


Date: Sat, 29 Apr 2006 11:32:42 +0300
From: Diomidis Spinellis <dds@aueb.gr>
Organization: Athens University of Economics and Business
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.2) Gecko/20060404 SeaMonkey/1.0.1
MIME-Version: 1.0
Newsgroups: comp.lang.c
Subject: Re: variadic without va_arg
References: <1146294990.717129.8650@j33g2000cwa.googlegroups.com>
In-Reply-To: <1146294990.717129.8650@j33g2000cwa.googlegroups.com>
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit
Bill Pursell wrote:
> I don't particularly enjoy using the va_start macro family, and I've
> noticed that the following code works.  I'm a little concerned about
> the fact that the prototypes for foo do not match.  Is this safe?
> 
> [tmp]$ cat q.c
> extern int foo(int x,...);
> 
> int
> main (int argc, char const*const* argv) /*:)*/
> {
>     foo(0);
>     foo(1,8);
>     foo(2,3,7);
>     foo(4,1,2,3,4);
>     return 0;
> }
> [tmp]$ cat r.c
> 
> int
> foo(int num, int a, int b, int c)
> {
>     switch(num) {
>     case 0: return 0;
>     case 1: return a;
>     case 2: return a+b;
>     case 3: return a+b+c;
>     default: return -1;
>     }
> }

According to the C99 standard (section 6.9.1) "If a function that 
accepts a variable number of arguments is defined without a parameter
type list that ends with the ellipsis notation, the behavior is undefined."

Your code works, because your compiler and processor architecture use an 
argument passing convention compatible with the 1970s style C.  At that 
time functions like printf were indeed called with fewer or more 
arguments than their specification and extra arguments or clever pointer 
arithmetic were used to access the remaining arguments.  These tricks 
were however not portable, and prompted the development of the Unix 
vararg and later the ANSI stdarg facilities.

Having said that I admit that processor architects and compiler vendors 
go to extreme lengths to make legacy code work.  I tried your example on 
some architectures I thought it would bomb (a SPARC, an Itanium, and an 
Alpha), and it worked correctly.  Still, there's no reason to write 
non-portable code: at the very least you demonstrate you're not playing 
by the rules.  If I was reading your code I would worry that other 
problems might also be lurking in it.

-- 
Diomidis Spinellis
Code Quality: The Open Source Perspective (Addison-Wesley 2006)
http://www.spinellis.gr/codequality?clc



Newsgroup comp.lang.c contents
Newsgroup list
Diomidis Spinellis home page

Creative Commons License Unless otherwise expressly stated, all original material on this page created by Diomidis Spinellis is licensed under a Creative Commons Attribution-Share Alike 3.0 Greece License.