tags:

views:

413

answers:

7

Can anyone confirm what the standard says about the default return type of vararg function. I was compiling the following code:

int main()
{
    maw(32,3,95,38,20,15);
    return 0;
}

int maw(int a,int b,...)
{
    int *p=&b,i=0;
    while(i++<a)
       printf("\t%d",*p++);
    return 0;
}

but it gave error:

foo.c:9: error: conflicting types for ‘maw’
foo.c:10: note: a parameter list with an ellipsis can’t match an empty parameter name list declaration
foo.c:4: error: previous implicit declaration of ‘maw’ was here

but if during the definition of maw, if I mention it as void maw(int a, int b, ...) the compilation is quite fine.

I can make out from this that the default return type of vararg function is probably not int.

What does the standard say in this regard? Can anybody confirm it for me?

+4  A: 

Declare maw() before main(), or prototype it before main(). Functions return the types that you assign to them, regardless of arguments (variadic or not).

Tim Post
+2  A: 

The problem is that you're calling the function before defining it, and not including a declaration. If you add a line like this:

int maw(int a, int b, ...);

Before your main() function, you'll be fine. The default ("implcit") is to assume a function returns int, and has an empty argument list. It's bad form to rely on the implicit declaration, you should declare all functions explicitly.

unwind
+1  A: 

It's nothing to do with the return type - it's the fact that you declared it at all. Put a declaration:

int maw(int a,int b,...);

before your use of the function in main()

anon
A: 

Add the declaration

int maw(int a,int b, ...);

before your main() function.

Currently, the call you make within your main() function implicitly defines maw(), that is, the compiler "guesses" what maw()'s return type is based on the information it is given within main(). If you declare maw() before it is called, you will not have this problem.

Artelius
+10  A: 

The other answers are correct, about putting the function prototype first.

Additionally, to be portable, do not access the ... arguments by using a direct pointer to the last (non-vararg) argument, because then you have to care about the alignment and stack direction of your target platform. Instead, use <stdarg.h> and the va_* macros for working with varargs.

Chris Jester-Young
+1 for pointing out the problem with direct access to the stack
Alnitak
+ for a nice answer after 4 "place it BEFORE the main" :)
claferri
A: 

hi guyz thanks for reply. I know that if I just standrized the code it will run perfectly.I hv done it.There is no problem with that. My point is what is the problem with this code.It should have run perfectly. Does'nt a code like this run without any error

int main() {

abc(); ..... return 0; }

abc() { ....... }

The problem is coming when a variable argument function is being used. I know what the standard say for default declration of the function. Hope you take my point .

mawia
Please edit the question or ask a new question. An answer is not a good place to ask more questions...
RBerteig
i was actually new to this forum so thanks for letting me know this rule.
mawia
@mawia, Its ok, SO is a forgiving place... the logic is that answers get sorted by score by default, so it is difficult to use them for a dialog.
RBerteig
A: 

As every answer (so far) has said: to avoid the errors, declare the function before its use, and as Chris Jester-Young points out, use the standard mechanisms for accessing the variadic arguments or suffer the pains of Undefined Behavior.

In this example, it is not that the declaration before use in this case is required because of the function's return type, but rather because it does not match the default signature for an undeclared function: int u(); that is, a function taking unspecified arguments returning an int. Specifically, the actual definition int maw(int,int,...) is inconsistent with different from the assumed declaration int maw() which causes GCC to say "conflicting types for ‘maw’".

Your second example

int main() {
  abc(); ..... return 0; 
}
abc() { ....... }

works because the later definition of abc doesn't contradict the default signature assumed when its first call was encountered. But just because it works doesn't make it good form because you get almost no type safety from the default signature.

Access to the variadic arguments (the ones matching the ...) really should be done through the standard mechanisms of stdarg.h, unless you are implementing a compiler and are the author of that compiler's stdarg.h. For instance, on some architectures those arguments may not even be passed on the stack, but they can still be located by the macros from stdarg.h.

Edit: I reworded the second paragraph to say what I meant in a different, and I hope clearer, way.

The compiler needs to know that the function is variadic before the first call because on some architectures, it might be required to pass the variadic parameters differently than normal parameters. That is especially true of certain register-window RISK architectures, and those that might pass the first 2 ints and first 2 floats in registers, but must put all variadics on the stack even if there is room in the regsisters.

A similar declare before use situation exists for functions that do not use the cdecl calling convention. You will usually run into this when linking modules written in Pascal or FORTRAN with modules written in C. However, many of the Windows API functions exported by the core DLLs assume a calling convention named stdcall and if the compiler were to use a cdecl style call, the program would crash (and the whole machine on Windows 9x or earlier).

RBerteig
as you said "Specifically, the actual definition int maw(int,int,...) is inconsistent with the assumed declaration int maw()"if it is consistent with the assuemed declration then why is it giving the error?can you shade some light on it?
mawia
"inconsistent" == "not consistent". That is, the two declarations are not consistent, which is what the error message is trying to say.
RBerteig
okay really thanks for reply.I wholeheartedly accept what you said.If i define in my 1st exmpl maw as void maw like thisvoid maw(int a,int b){.......}I think it is more confilicting,but it is not giving any error and compiling quite fine.is it some undefined behaviour or else.thanks
mawia
On my Windows box, MinGW's GCC 3.4.5 simply says "error: conflicting types for 'maw'" for both the original variadic example and for void maw(int a, int b){}. Regardless, unless the implicit declaration matches the actual definition, you are invoking undefined behavior.
RBerteig