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