Variable Arguments function

Go To Last Post
19 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Is there a way to have a function accept a variable number of arguments, possibly none(emphasis on that last part)?

When I try

void foo(...) {

}

I get an error: "ISO C requires a named argument before '...'"

I have a function that has a timeout value. If the user doesn't pass an argument, the function would use some default (hard coded) value. If they do pass an argument, then it uses that instead.

Science is not consensus. Science is numbers.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ANSI C requires that there be at least one fixed argument before the ellipses. So by definition you can not pass zero arguments to a variadic function. That's why you are getting the compiler complaint you noted.

Here is a good explanation on the subject.
http://www.chemie.fu-berlin.de/chemnet/use/info/libc/libc_28.html

Jerry

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

hobbss wrote:
Is there a way to have a function accept a variable number of arguments, possibly none(emphasis on that last part)?
How should that work?

How could the callee determine the number of arguments out of nothing?

avrfreaks does not support Opera. Profile inactive.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks for the responses (and reference).

I am not sure I understand Sprinter's question, but I do understand that it doesn't work.

Science is not consensus. Science is numbers.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

hobbss wrote:
Thanks for the responses (and reference).

I am not sure I understand Sprinter's question, but I do understand that it doesn't work.

What SprinterSB is saying is, if you pass it zero arguments, how would it know how many arguments to deal with in the varadic function. The same thing I said by saying you can't have zero arguments to a varadic function. Same thing but only different.

Jerry

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Use the C++ compiler. Then you can specify default values for your parameters.

Sid

Life... is a state of mind

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

Use the C++ compiler.

+1

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

C++ won't help:

  1. Even with C++, you cannot have varargs function without a named argument.
  2. Neither name mangling nor default parameters will do: What would be the default parameters for printf, for example?

avrfreaks does not support Opera. Profile inactive.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If you don't want to pass any arguments, just make the first argument an empty string. Since there are no format specifiers in an empty string, it knows not to look for any.

printf ("");

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

C++ won't help:

I meant function overloading and/or optional parameters, not va_args. So:

void foo();
void foo(char c);
void foo(int n, long l = 1234, short s = 2);

then call something like:

foo();
foo('A');
foo(4321);
foo(0, 0xDEADBEEF);
foo(17, 0xBABEFACE, 0xBAAD);

etc.

That certainly allows for a variant with no parameters.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

SprinterSB wrote:
C++ won't help:
  1. Even with C++, you cannot have varargs function without a named argument.
  2. Neither name mangling nor default parameters will do: What would be the default parameters for printf, for example?
True, if the OP really wants to have what he initially asked for. But how often is that actually the case? ;-)
Quote:
I have a function that has a timeout value. If the user doesn't pass an argument, the function would use some default (hard coded) value. If they do pass an argument, then it uses that instead.

For this specific situation (default for only one parameter) a macro is also a practicable option (IMO):

#define timeout_default() timeout(DEFAULT_TIMEOUT)

Stefan Ernst

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You can also (ab)use C and just for the fun of hacking:

#define TIMEOUT_DEFAULT 10

extern void set_timeout (unsigned char);

#define SET_TIMEOUT(TO) \
    set_timeout ((unsigned char) (*#TO ? TO+0 : TIMEOUT_DEFAULT))
 
void f (void)
{
    SET_TIMEOUT ();
    SET_TIMEOUT (1);
    SET_TIMEOUT (TIMEOUT_DEFAULT + 1);
}

avr-gcc translates:

f:
	ldi r24,lo8(10)
	rcall set_timeout
	ldi r24,lo8(1)
	rcall set_timeout
	ldi r24,lo8(11)
	rjmp set_timeout

avrfreaks does not support Opera. Profile inactive.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I would like to think that I usually do want what I am asking for. However, in this case, I think that Stefan's suggestion is the closest behavior to what I am looking for. Thank you again for the responses.

Science is not consensus. Science is numbers.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Only because you have given into the big C++ compiler scare. (You're in good company, most people in here are very afraid of it.)

There are many other benefits related to compiling your C sources with a C++ compiler. I am not aware of a single downside.

Sid

Life... is a state of mind

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

I am not aware of a single downside.

Just to warn that I think the transition to _flash in 4.7/4.8 is only for C not C++ which is one small possible downside.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
Quote:

I am not aware of a single downside.

Just to warn that I think the transition to _flash in 4.7/4.8 is only for C not C++ which is one small possible downside.

If that's the way it's going to play out, it's an artificially created downside.

Maybe Atmel should hire somebody to get their tools up to date then, instead of relying on the quirks of whoever volunteers. They may be okay with the market situation now, but things change quickly in this industry when the market leaders fall asleep.

Whatever. It's not like C++ is going to stop working just because somebody threw a now toy into C.

A few years ago it was impossible to convince microcontroller developers that there was any point in using C.

Sid

Life... is a state of mind

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Well Atmel show no sign of contributing to the compiler development at all. They have a private branch to which they've added new device support but don't appear to be interested in sharing. Meanwhile there's just a few people (like Georg-Johann Lay: SprinterSB here) who are doing the work to add great features like _flash to the generic C compiler but no sign of Atmel offering to help such as providing resource to port work from the C to C++ compiler. No doubt when the work is stable they will merge a snapshot into their private tree though. (though they may be forced into looking at the port to C++ at that point as they presumably have to offer all compiler users the same features).

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If he is doing all the AVR-related work, they should pay him for it - whether he is happy to do it for free or not. What's good for the customers is good for them. I am very surprised to see indications that they don't understand that.

Sid

Life... is a state of mind

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

I am very surprised to see indications that they don't understand that.

Stick around you'll get the picture after a while. It seems like Atmel want to give the outward impression that AS6 comes with "their" C compiler. By taking mainline 4.6.2 and making a branch then adding new device support to that it means for example that if you want to program tiny 4/5/9/10 or these new Xmega E5 or whatever you have no option but to use their variant of the compiler. You cannot choose to go to 4.7 or 4.8 as the work they did has not been back-ported to the GCC trunk so you cannot taste flavours of "new stuff" (like _flash) but are hostage to Atmel's fortune. They simply don't seem willing or able to play the GPL me as it's supposed to be. But, hey, they have a lot of customers who think they're now providing THEIR pretty splendid C/C++ compiler for free ;-). When prompted to publish their own patches (device support) under the requirements of GPL they do eventually do so. In that sense they are not in violation of GPL. But maybe not in practice but definitely in spirit. It's not clear whether this is deliberate or whether the GCC team they use (out-sourced, off-shore it would seem) don't seem to understand the spirit of GPL development.