void func()
In practice, an empty parameter means any argument is accepted.
void func(void) accepts no argument.
But in Standard C99, I find such lines:
6.7.5.3 Function declarators (including prototypes)
14 An identifier list declares only the identifiers of the parameters of the function. An empty list in a function declarator that is part of a definition of that function specifies that the function has no parameters. The empty list in a function declarator that is not part of a definition of that function specifies that no information about the number or types of the parameters is supplied.
According to the standard, are func() and func(void) the same?
TL;DR
In declarations,
void func1(); // obsolescent
void func2(void);
the behaviour is quite different. The first one declares a function without any prototype - and it may take any number of arguments! Whereas the latter declares a function with a prototype, that has no parameters and accepts no arguments.
In definitions
void func1() { } // obsolescent
and
void func2(void) { }
The former declares and defines a function func1 that has no parameters and no prototype
The latter declares and defines a function func2 with a prototype that has no parameters.
These two behave distinctly in that whereas the C compiler must print a diagnostic message when calling a prototyped function with wrong number of arguments, it needn't do so when calling a function without prototype.
I.e, given the definitions above
func1(1, 2, 3); // need not produce a diagnostic message
func2(1, 2, 3); // must always produce a diagnostic message
// as it is a constraint violation
However both calls are illegal in strictly-conforming programs as they're explicitly undefined behaviour as per 6.5.2.2p6.
Furthermore, the empty parentheses are considered an obsolescent feature:
The use of function declarators with empty parentheses (not prototype-format parameter type declarators) is an obsolescent feature.
and
The use of function definitions with separate parameter identifier and declaration lists (not prototype-format parameter type and identifier declarators) is an obsolescent feature.
In detail
There are 2 related, yet distinct concepts: parameters and arguments.
arguments are the values passed into the function.
parameters are the names/variables within the function that are set to the values of the arguments when the function entered
In the following excerpt:
int foo(int n, char c) {
...
}
...
foo(42, ch);
n and c are parameters. 42 and ch are arguments.
The quoted excerpt only concerns the parameters of a function, but doesn't mention anything about the prototype or arguments to the function.
The declaration void func1() means that the function func1 can be called with any number of arguments, i.e. no information about the number of arguments is specified (as a separate declaration, C99 specifies this as "function with no parameter specification), whereas the declaration void func2(void) means that the function func2 does not accept any arguments at all.
The quote in your question means that within a function definition, void func1() and void func2(void) both signal them that there are no parameters, i.e. variable names that are set to the values of the arguments when the function is entered. The void func() {} contrasts with void func(); the former declares that func indeed takes no parameters, whereas the latter is a declaration for a function func for which neither parameters nor their types are specified (a declaration without prototype).
However, they yet differ definition-wise in that
The definition void func1() {} doesn't declare a prototype, whereas void func2(void) {} does, because () is not a parameter type list, whereas (void) is a parameter type list (6.7.5.3.10):
The special case of an unnamed parameter of type void as the only item in the list specifies that the function has no parameters.
and further 6.9.1.7
If the declarator includes a parameter type list, the
list also specifies the types of all the parameters; such a declarator also serves as a function prototype for later calls to the same function in the same translation unit. If the declarator includes an identifier list, the types of the parameters shall be declared in a following declaration list. In either case, the type of each parameter is adjusted as described in 6.7.5.3 for a parameter type list; the resulting type shall be an object type.
The declarator of function definition for func1 does not contain a parameter type list, and thus the function then doesn't have a prototype.
void func1() { ... } can still be called with any number of arguments, whereas it is a compile-time error to call void func2(void) { ... } with any arguments (6.5.2.2):
If the expression that denotes the called function has a type that includes a prototype, the number of arguments shall agree with the number of parameters. Each argument shall have a type such that its value may be assigned to an object with the unqualified version of the type of its corresponding parameter.
(emphasis mine)
This is a constraint, which according of the standard says that a conforming implementation must display at least one diagnostic message about this problem. But since func1 doesn't have a prototype, a conforming implementation is not required to produce any diagnostics.
However, if the number of arguments does not equal the number of parameters, the behaviour is undefined 6.5.2.2p6:
If the expression that denotes the called function has a type that does not include a prototype, [...] If the number of arguments does not equal the number of parameters, the behavior is undefined.
So in theory a conforming C99 compiler is also allowed to error or diagnose a warning in this case. StoryTeller provided evidence that clang might diagnose this; however, my GCC doesn't seem to do it (and this might also be required for it to be compatible with some old obscure code too):
void test() { }
void test2(void) { }
int main(void) {
test(1, 2);
test2(1, 2);
}
When the above program is compiled with gcc -std=c99 test.c -Wall -Werror, the output is:
test.c: In function ‘main’:
test.c:7:5: error: too many arguments to function ‘test2’
test2(1, 2);
^~~~~
test.c:3:6: note: declared here
void test2(void) { }
^~~~~
That is, the arguments are not checked at all against the parameters of a function whose declaration in definition is not prototyped (test) whereas GCC considers it as a compile-time error to specify any arguments to a prototyped function (test2); any conforming implementation must diagnose this as it is a constraint violation.
The significant part of the quote is highlighted in bold below:
6.7.5.3 Function declarators (including prototypes) 14 An identifier list declares only the identifiers of the parameters of the function. An empty list in a function declarator that is part of a definition of that function specifies that the function has no parameters. The empty list in a function declarator that is not part of a definition of that function specifies that no information about the number or types of the parameters is supplied.
So, when the parameter list is empty for a function with its body, they are the same. But of it is just a declaration of a function.
void function1(); // No information about arguments
void function2(void); // Function with zero arguments
void function3() {
// Zero arguments
}
void function4(void) {
// Zero arguments
}
according to the standard, func() and func(void) is the same?
No. func(void) says the function takes no arguments at all; whereas func() says the function takes an unspecified number of arguments. Both are valid but the func() style are obsolete and shouldn't be used.
This is an artifact from pre-standard C. C99 marked this as obsolete.
6.11.6 Function declarators:
The use of function declarators with empty parentheses (not prototype-format parameter type declarators) is an obsolescent feature.
As of C11, it still remains as obsolescent and hasn't been removed from the standard.
The empty parameter list inside a function definition means that it does not include a prototype nor has any parameters.
C11 §6.9.1/7 Function definitions
(emphasis in ongoing quotes is mine)
The declarator in a function definition specifies the name of the
function being defined and the identifiers of its parameters. If the
declarator includes a parameter type list, the list also specifies the
types of all the parameters; such a declarator also serves as a
function prototype for later calls to the same function in the same
translation unit.
The question asks:
according to the standard, func() and func(void) is the same?
No. The essential difference between void func() and void func(void) lies in their calls.
C11 §6.5.2.2/2 Function calls (within constraints section):
If the expression that denotes the called function has a type that
includes a prototype, the number of arguments shall agree with the
number of parameters. Each argument shall have a type such that its
value may be assigned to an object with the unqualified version of the
type of its corresponding parameter.
Notice that parameters ≠ arguments. The function may contain no parameters, but it may have multiple arguments.
As a function defined with empty parameters does not introduce a prototype, it's not checked against its calls, so in theory it may be supplied with whatever number of arguments.
However, it is technically an undefined behavior (UB) to call such function with at least one argument (see Antti Haapala's comments).
C11 §6.5.2.2/6 Function calls (within semantics section):
If the number of arguments does not equal the number of parameters,
the behavior is undefined.
Hence, the difference is subtle:
When a function is defined with void, it won't compile when number of arguments don't match with parameters (along with their types), because of constraint violation (§6.5.2.2/2). Such a situation requires diagnostic message from a conforming compiler.
If it is defined with empty parameters, it may or may not compile (there is no requirement for a diagnostic message from a conforming compiler), however it's UB to call such function.
Example:
#include <stdio.h>
void func1(void) { puts("foo"); }
void func2() { puts("foo"); }
int main(void)
{
func1(1, 2); // constraint violation, it shouldn't compile
func2(3, 4); // may or may not compile, UB when called
return 0;
}
Note that an optimizing compiler may cut off the arguments in such a case. For instance, this is how Clang compiles the above code (excluding func1's call) with -01 on x86-64 according to the SysV ABI calling conventions:
main: # #main
push rax ; align stack to the 16-byte boundary
call func2 ; call func2 (no arguments given)
xor eax, eax ; set zero as return value
pop rcx ; restore previous stack position (RSP)
ret
Related
This question already has answers here:
func() vs func(void) in C99
(4 answers)
Closed 2 years ago.
Note: this is not the same as func() vs func(void) in c99, because the question here specifically asks about the implementation of a zero-argument function following a valid declaration.
Should the implementation of a zero-argument include the void keyword? Specifically, does the C standard have anything to say about the implementation of the following two functions? Note that both foo1 and foo2 are declared as zero-argument functions; the only difference is in the implementation, not in the declaration:
#include <stdio.h>
int foo1(void); // inform compiler that foo1 and foo2 are zero-args fns.
int foo2(void);
int main() {
printf("%d\n", foo1());
printf("%d\n", foo2());
return 0;
}
int foo1(void) { return 22; }
int foo2() { return 22; }
I note that gcc -Wall -std=c99 -Wpedantic foo.c -o foo compiles and executes without any warnings or errors, but is there any violation of the standard going on?
The code you have posted is correct. int foo2(void); declares foo2 as taking no arguments, and forms a prototype.
The function definition must be compatible with this; and a definition with empty parentheses is compatible with this prototype. This is specified in C11 6.7.6.3/15, which is a mouthful:
For two function types to be compatible, both shall specify compatible return types. Moreover, the parameter type lists, if both are present, shall agree in the number of parameters and in use of the ellipsis terminator; corresponding parameters shall have compatible types. If one type has a parameter type list and the other type is specified by a function declarator that is not part of a function definition and that contains an empty identifier list, the parameter list shall not have an ellipsis terminator and the type of each parameter shall be compatible with the type that results from the application of the default argument promotions. If one type has a parameter type list and the other type is specified by a function definition that contains a (possibly empty) identifier list, both shall agree in the number of parameters, and the type of each prototype parameter shall be compatible with the type that results from the application of the default argument
promotions to the type of the corresponding identifier. (In the determination of type compatibility and of a composite type, each parameter declared with function or array type is taken as having the adjusted type and each parameter declared with qualified type is taken as having the unqualified version of its declared type.)
The reason there's so much text on this point is that C originally only had K&R style functions, and then prototypes were added . So there has to be text to cover all possible combinations of K&R style mixed with prototype style . The section beginning with my bolded part refers to using a K&R-style function definition when the function has previously been declared with a prototype.
Also relevant: use of empty parentheses is obsolescent in C11 (6.11.6).
Certain features are obsolescent, which means that they may be considered for
withdrawal in future revisions of this International Standard. They are retained because of their widespread use, but their use in new implementations or new programs is discouraged.
void func()
In practice, an empty parameter means any argument is accepted.
void func(void) accepts no argument.
But in Standard C99, I find such lines:
6.7.5.3 Function declarators (including prototypes)
14 An identifier list declares only the identifiers of the parameters of the function. An empty list in a function declarator that is part of a definition of that function specifies that the function has no parameters. The empty list in a function declarator that is not part of a definition of that function specifies that no information about the number or types of the parameters is supplied.
According to the standard, are func() and func(void) the same?
TL;DR
In declarations,
void func1(); // obsolescent
void func2(void);
the behaviour is quite different. The first one declares a function without any prototype - and it may take any number of arguments! Whereas the latter declares a function with a prototype, that has no parameters and accepts no arguments.
In definitions
void func1() { } // obsolescent
and
void func2(void) { }
The former declares and defines a function func1 that has no parameters and no prototype
The latter declares and defines a function func2 with a prototype that has no parameters.
These two behave distinctly in that whereas the C compiler must print a diagnostic message when calling a prototyped function with wrong number of arguments, it needn't do so when calling a function without prototype.
I.e, given the definitions above
func1(1, 2, 3); // need not produce a diagnostic message
func2(1, 2, 3); // must always produce a diagnostic message
// as it is a constraint violation
However both calls are illegal in strictly-conforming programs as they're explicitly undefined behaviour as per 6.5.2.2p6.
Furthermore, the empty parentheses are considered an obsolescent feature:
The use of function declarators with empty parentheses (not prototype-format parameter type declarators) is an obsolescent feature.
and
The use of function definitions with separate parameter identifier and declaration lists (not prototype-format parameter type and identifier declarators) is an obsolescent feature.
In detail
There are 2 related, yet distinct concepts: parameters and arguments.
arguments are the values passed into the function.
parameters are the names/variables within the function that are set to the values of the arguments when the function entered
In the following excerpt:
int foo(int n, char c) {
...
}
...
foo(42, ch);
n and c are parameters. 42 and ch are arguments.
The quoted excerpt only concerns the parameters of a function, but doesn't mention anything about the prototype or arguments to the function.
The declaration void func1() means that the function func1 can be called with any number of arguments, i.e. no information about the number of arguments is specified (as a separate declaration, C99 specifies this as "function with no parameter specification), whereas the declaration void func2(void) means that the function func2 does not accept any arguments at all.
The quote in your question means that within a function definition, void func1() and void func2(void) both signal them that there are no parameters, i.e. variable names that are set to the values of the arguments when the function is entered. The void func() {} contrasts with void func(); the former declares that func indeed takes no parameters, whereas the latter is a declaration for a function func for which neither parameters nor their types are specified (a declaration without prototype).
However, they yet differ definition-wise in that
The definition void func1() {} doesn't declare a prototype, whereas void func2(void) {} does, because () is not a parameter type list, whereas (void) is a parameter type list (6.7.5.3.10):
The special case of an unnamed parameter of type void as the only item in the list specifies that the function has no parameters.
and further 6.9.1.7
If the declarator includes a parameter type list, the
list also specifies the types of all the parameters; such a declarator also serves as a function prototype for later calls to the same function in the same translation unit. If the declarator includes an identifier list, the types of the parameters shall be declared in a following declaration list. In either case, the type of each parameter is adjusted as described in 6.7.5.3 for a parameter type list; the resulting type shall be an object type.
The declarator of function definition for func1 does not contain a parameter type list, and thus the function then doesn't have a prototype.
void func1() { ... } can still be called with any number of arguments, whereas it is a compile-time error to call void func2(void) { ... } with any arguments (6.5.2.2):
If the expression that denotes the called function has a type that includes a prototype, the number of arguments shall agree with the number of parameters. Each argument shall have a type such that its value may be assigned to an object with the unqualified version of the type of its corresponding parameter.
(emphasis mine)
This is a constraint, which according of the standard says that a conforming implementation must display at least one diagnostic message about this problem. But since func1 doesn't have a prototype, a conforming implementation is not required to produce any diagnostics.
However, if the number of arguments does not equal the number of parameters, the behaviour is undefined 6.5.2.2p6:
If the expression that denotes the called function has a type that does not include a prototype, [...] If the number of arguments does not equal the number of parameters, the behavior is undefined.
So in theory a conforming C99 compiler is also allowed to error or diagnose a warning in this case. StoryTeller provided evidence that clang might diagnose this; however, my GCC doesn't seem to do it (and this might also be required for it to be compatible with some old obscure code too):
void test() { }
void test2(void) { }
int main(void) {
test(1, 2);
test2(1, 2);
}
When the above program is compiled with gcc -std=c99 test.c -Wall -Werror, the output is:
test.c: In function ‘main’:
test.c:7:5: error: too many arguments to function ‘test2’
test2(1, 2);
^~~~~
test.c:3:6: note: declared here
void test2(void) { }
^~~~~
That is, the arguments are not checked at all against the parameters of a function whose declaration in definition is not prototyped (test) whereas GCC considers it as a compile-time error to specify any arguments to a prototyped function (test2); any conforming implementation must diagnose this as it is a constraint violation.
The significant part of the quote is highlighted in bold below:
6.7.5.3 Function declarators (including prototypes) 14 An identifier list declares only the identifiers of the parameters of the function. An empty list in a function declarator that is part of a definition of that function specifies that the function has no parameters. The empty list in a function declarator that is not part of a definition of that function specifies that no information about the number or types of the parameters is supplied.
So, when the parameter list is empty for a function with its body, they are the same. But of it is just a declaration of a function.
void function1(); // No information about arguments
void function2(void); // Function with zero arguments
void function3() {
// Zero arguments
}
void function4(void) {
// Zero arguments
}
according to the standard, func() and func(void) is the same?
No. func(void) says the function takes no arguments at all; whereas func() says the function takes an unspecified number of arguments. Both are valid but the func() style are obsolete and shouldn't be used.
This is an artifact from pre-standard C. C99 marked this as obsolete.
6.11.6 Function declarators:
The use of function declarators with empty parentheses (not prototype-format parameter type declarators) is an obsolescent feature.
As of C11, it still remains as obsolescent and hasn't been removed from the standard.
The empty parameter list inside a function definition means that it does not include a prototype nor has any parameters.
C11 §6.9.1/7 Function definitions
(emphasis in ongoing quotes is mine)
The declarator in a function definition specifies the name of the
function being defined and the identifiers of its parameters. If the
declarator includes a parameter type list, the list also specifies the
types of all the parameters; such a declarator also serves as a
function prototype for later calls to the same function in the same
translation unit.
The question asks:
according to the standard, func() and func(void) is the same?
No. The essential difference between void func() and void func(void) lies in their calls.
C11 §6.5.2.2/2 Function calls (within constraints section):
If the expression that denotes the called function has a type that
includes a prototype, the number of arguments shall agree with the
number of parameters. Each argument shall have a type such that its
value may be assigned to an object with the unqualified version of the
type of its corresponding parameter.
Notice that parameters ≠ arguments. The function may contain no parameters, but it may have multiple arguments.
As a function defined with empty parameters does not introduce a prototype, it's not checked against its calls, so in theory it may be supplied with whatever number of arguments.
However, it is technically an undefined behavior (UB) to call such function with at least one argument (see Antti Haapala's comments).
C11 §6.5.2.2/6 Function calls (within semantics section):
If the number of arguments does not equal the number of parameters,
the behavior is undefined.
Hence, the difference is subtle:
When a function is defined with void, it won't compile when number of arguments don't match with parameters (along with their types), because of constraint violation (§6.5.2.2/2). Such a situation requires diagnostic message from a conforming compiler.
If it is defined with empty parameters, it may or may not compile (there is no requirement for a diagnostic message from a conforming compiler), however it's UB to call such function.
Example:
#include <stdio.h>
void func1(void) { puts("foo"); }
void func2() { puts("foo"); }
int main(void)
{
func1(1, 2); // constraint violation, it shouldn't compile
func2(3, 4); // may or may not compile, UB when called
return 0;
}
Note that an optimizing compiler may cut off the arguments in such a case. For instance, this is how Clang compiles the above code (excluding func1's call) with -01 on x86-64 according to the SysV ABI calling conventions:
main: # #main
push rax ; align stack to the 16-byte boundary
call func2 ; call func2 (no arguments given)
xor eax, eax ; set zero as return value
pop rcx ; restore previous stack position (RSP)
ret
I've just come across someone's C code that I'm confused as to why it is compiling. There are two points I don't understand.
The function prototype has no parameters compared to the actual function definition.
The parameter in the function definition does not have a type.
#include <stdio.h>
int func();
int func(param)
{
return param;
}
int main()
{
int bla = func(10);
printf("%d", bla);
}
Why does this work?
I have tested it in a couple of compilers, and it works fine.
All the other answers are correct, but just for completion
A function is declared in the following manner:
return-type function-name(parameter-list,...) { body... }
return-type is the variable type that the function returns. This can not be an array type or a function type. If not given, then int
is assumed.
function-name is the name of the function.
parameter-list is the list of parameters that the function takes separated by commas. If no parameters are given, then the function
does not take any and should be defined with an empty set of
parenthesis or with the keyword void. If no variable type is in front
of a variable in the paramater list, then int is assumed. Arrays and
functions are not passed to functions, but are automatically converted
to pointers. If the list is terminated with an ellipsis (,...), then
there is no set number of parameters. Note: the header stdarg.h can be
used to access arguments when using an ellipsis.
And again for the sake of completeness. From C11 specification 6:11:6 (page: 179)
The use of function declarators with empty parentheses (not
prototype-format parameter type declarators) is an obsolescent
feature.
In C func() means that you can pass any number of arguments. If you want no arguments then you have to declare as func(void). The type you're passing to your function, if not specified defaults to int.
int func(); is an obsolescent function declaration from the days when there was no C standard, i.e. the days of K&R C (before 1989, the year the first "ANSI C" standard was published).
Remember that there were no prototypes in K&R C and the keyword void was not yet invented. All you could do was to tell the compiler about the return type of a function. The empty parameter list in K&R C means "an unspecified but fixed" number of arguments. Fixed means that you must call the function with the same number of args each time (as opposed to a variadic function like printf, where the number and type can vary for each call).
Many compilers will diagnose this construct; in particular gcc -Wstrict-prototypes will tell you "function declaration isn't a prototype", which is spot on, because it looks like a prototype (especially if you are poisoned by C++!), but isn't. It's an old style K&R C return type declaration.
Rule of thumb: Never leave an empty parameter list declaration empty, use int func(void) to be specific.
This turns the K&R return type declaration into a proper C89 prototype. Compilers are happy, developers are happy, static checkers are happy. Those mislead by^W^Wfond of C++ may cringe, though, because they need to type extra characters when they try to exercise their foreign language skills :-)
The empty parameter list means "any arguments", so the definition isn't wrong.
The missing type is assumed to be int.
I would consider any build that passes this to be lacking in configured warning/error level though, there's no point in being this allowing for actual code.
It's K&R style function declaration and definition. From C99 Standard (ISO/IEC 9899:TC3)
Section 6.7.5.3 Function Declarators (including prototypes)
An identifier list declares only the identifiers of the parameters of the function. An empty
list in a function declarator that is part of a definition of that function specifies that the
function has no parameters. The empty list in a function declarator that is not part of a
definition of that function specifies that no information about the number or types of the
parameters is supplied. (If both function types are "old style", parameter types are not compared.)
Section 6.11.6 Function declarators
The use of function declarators with empty parentheses (not prototype-format parameter
type declarators) is an obsolescent feature.
Section 6.11.7 Function definitions
The use of function definitions with separate parameter identifier and declaration lists
(not prototype-format parameter type and identifier declarators) is an obsolescent feature.
Which the old style means K&R style
Example:
Declaration: int old_style();
Definition:
int old_style(a, b)
int a;
int b;
{
/* something to do */
}
C assumes int if no type is given on function return type and parameter list. Only for this rule following weird things are possible.
A function definition looks like this.
int func(int param) { /* body */}
If its a prototype you write
int func(int param);
In prototype you can only specify the type of parameters. Parameters' name is not mandatory. So
int func(int);
Also if you dont specify parameter type but name int is assumed as type.
int func(param);
If you go farther, following works too.
func();
Compiler assumes int func() when you write func(). But dont put func() inside a function body. That'll be a function call
As stated #Krishnabhadra, all previous responses from other users, have a correct interpretation, and I just want to make a more detailed analysis of some points.
In the Old-C as in ANSI-C the "untyped formal parameter", take the dimencion of your work register or instruction depth capability (shadow registers or instruction cumulative cycle), in an 8bit MPU, will be an int16, in a 16bit MPU and so will be an int16 an so on, in the case 64bit architectures may choose to compile options like: -m32.
Although it seems simpler implementation at high level,
For pass multiple parameters, the work of the programmer in the control dimencion data type step, becomes more demanding.
In other cases, for some microprocessors architectures, the ANSI compilers customized, leveraged some of this old features to optimize the use of the code, forcing the location of these "untyped formal parameters" to work within or outside the work register, today you get almost the same with the use of "volatile" and "register".
But it should be noted that the most modern compilers,
not make any distinction between the two types of parameters declaration.
Examples of a compilation with gcc under linux:
In any case the statement of the prototype locally is of no use, because there is no call without parameters reference to this prototype will be remiss.
If you use the system with "untyped formal parameter", for an external call, proceed to generate a declarative prototype data type.
Like this:
int myfunc(int param);
Regarding parameter type, there are already correct answers here but if you want to hear it from the compiler you can try adding some flags (flags are almost always a good idea anyways).
compiling your program using gcc foo.c -Wextra I get:
foo.c: In function ‘func’:
foo.c:5:5: warning: type of ‘param’ defaults to ‘int’ [-Wmissing-parameter-type]
strangely -Wextra doesn't catch this for clang (it doesn't recognize -Wmissing-parameter-type for some reason, maybe for historical ones mentioned above) but -pedantic does:
foo.c:5:10: warning: parameter 'param' was not declared,
defaulting to type 'int' [-pedantic]
int func(param)
^
1 warning generated.
And for prototype issue as said again above int func() refers to arbitrary parameters unless you exclicitly define it as int func(void) which would then give you the errors as expected:
foo.c: In function ‘func’:
foo.c:6:1: error: number of arguments doesn’t match prototype
foo.c:3:5: error: prototype declaration
foo.c: In function ‘main’:
foo.c:12:5: error: too many arguments to function ‘func’
foo.c:5:5: note: declared here
or in clang as:
foo.c:5:5: error: conflicting types for 'func'
int func(param)
^
foo.c:3:5: note: previous declaration is here
int func(void);
^
foo.c:12:20: error: too many arguments to function call, expected 0, have 1
int bla = func(10);
~~~~ ^~
foo.c:3:1: note: 'func' declared here
int func(void);
^
2 errors generated.
If the function declaration has no parameters i.e. empty then it is taking unspecified number of arguments. If you want to make it take no arguments then change it to:
int func(void);
This is why I typically advise people to compile their code with:
cc -Wmissing-variable-declarations -Wstrict-variable-declarations -Wold-style-definition
These flags enforce a couple of things:
-Wmissing-variable-declarations: It is impossible to declare a non-static function without getting a prototype first. This makes it more likely that a prototype in a header file matches with the actual definition. Alternatively, it enforces that you add the static keyword to functions that don't need to be visible publicly.
-Wstrict-variable-declarations: The prototype must properly list the arguments.
-Wold-style-definition: The function definition itself must also properly list the arguments.
These flags are also used by default in a lot of Open Source projects. For example, FreeBSD has these flags enabled when building with WARNS=6 in your Makefile.
In the old-style declarator,
the identifier list must be absent unless
the declarator is used in the head of a function definition
(Par.A.10.1). No information about the types of the parameters is
supplied by the declaration. For example, the declaration
int f(), *fpi(), (*pfi)();
declares a function f returning an integer, a function fpi returning a pointer to an integer, >and a pointer pfi to a function returning an integer. In none of these are the parameter types >specified; they are old-style.
In the new-style declaration
int strcpy(char *dest, const char *source), rand(void);
strcpy is a
function returning int, with two arguments, the first a character
pointer, and the second a pointer to constant characters
SOURCE:- K&R book
I hope it cleared your doubt..
I've just come across someone's C code that I'm confused as to why it is compiling. There are two points I don't understand.
The function prototype has no parameters compared to the actual function definition.
The parameter in the function definition does not have a type.
#include <stdio.h>
int func();
int func(param)
{
return param;
}
int main()
{
int bla = func(10);
printf("%d", bla);
}
Why does this work?
I have tested it in a couple of compilers, and it works fine.
All the other answers are correct, but just for completion
A function is declared in the following manner:
return-type function-name(parameter-list,...) { body... }
return-type is the variable type that the function returns. This can not be an array type or a function type. If not given, then int
is assumed.
function-name is the name of the function.
parameter-list is the list of parameters that the function takes separated by commas. If no parameters are given, then the function
does not take any and should be defined with an empty set of
parenthesis or with the keyword void. If no variable type is in front
of a variable in the paramater list, then int is assumed. Arrays and
functions are not passed to functions, but are automatically converted
to pointers. If the list is terminated with an ellipsis (,...), then
there is no set number of parameters. Note: the header stdarg.h can be
used to access arguments when using an ellipsis.
And again for the sake of completeness. From C11 specification 6:11:6 (page: 179)
The use of function declarators with empty parentheses (not
prototype-format parameter type declarators) is an obsolescent
feature.
In C func() means that you can pass any number of arguments. If you want no arguments then you have to declare as func(void). The type you're passing to your function, if not specified defaults to int.
int func(); is an obsolescent function declaration from the days when there was no C standard, i.e. the days of K&R C (before 1989, the year the first "ANSI C" standard was published).
Remember that there were no prototypes in K&R C and the keyword void was not yet invented. All you could do was to tell the compiler about the return type of a function. The empty parameter list in K&R C means "an unspecified but fixed" number of arguments. Fixed means that you must call the function with the same number of args each time (as opposed to a variadic function like printf, where the number and type can vary for each call).
Many compilers will diagnose this construct; in particular gcc -Wstrict-prototypes will tell you "function declaration isn't a prototype", which is spot on, because it looks like a prototype (especially if you are poisoned by C++!), but isn't. It's an old style K&R C return type declaration.
Rule of thumb: Never leave an empty parameter list declaration empty, use int func(void) to be specific.
This turns the K&R return type declaration into a proper C89 prototype. Compilers are happy, developers are happy, static checkers are happy. Those mislead by^W^Wfond of C++ may cringe, though, because they need to type extra characters when they try to exercise their foreign language skills :-)
The empty parameter list means "any arguments", so the definition isn't wrong.
The missing type is assumed to be int.
I would consider any build that passes this to be lacking in configured warning/error level though, there's no point in being this allowing for actual code.
It's K&R style function declaration and definition. From C99 Standard (ISO/IEC 9899:TC3)
Section 6.7.5.3 Function Declarators (including prototypes)
An identifier list declares only the identifiers of the parameters of the function. An empty
list in a function declarator that is part of a definition of that function specifies that the
function has no parameters. The empty list in a function declarator that is not part of a
definition of that function specifies that no information about the number or types of the
parameters is supplied. (If both function types are "old style", parameter types are not compared.)
Section 6.11.6 Function declarators
The use of function declarators with empty parentheses (not prototype-format parameter
type declarators) is an obsolescent feature.
Section 6.11.7 Function definitions
The use of function definitions with separate parameter identifier and declaration lists
(not prototype-format parameter type and identifier declarators) is an obsolescent feature.
Which the old style means K&R style
Example:
Declaration: int old_style();
Definition:
int old_style(a, b)
int a;
int b;
{
/* something to do */
}
C assumes int if no type is given on function return type and parameter list. Only for this rule following weird things are possible.
A function definition looks like this.
int func(int param) { /* body */}
If its a prototype you write
int func(int param);
In prototype you can only specify the type of parameters. Parameters' name is not mandatory. So
int func(int);
Also if you dont specify parameter type but name int is assumed as type.
int func(param);
If you go farther, following works too.
func();
Compiler assumes int func() when you write func(). But dont put func() inside a function body. That'll be a function call
As stated #Krishnabhadra, all previous responses from other users, have a correct interpretation, and I just want to make a more detailed analysis of some points.
In the Old-C as in ANSI-C the "untyped formal parameter", take the dimencion of your work register or instruction depth capability (shadow registers or instruction cumulative cycle), in an 8bit MPU, will be an int16, in a 16bit MPU and so will be an int16 an so on, in the case 64bit architectures may choose to compile options like: -m32.
Although it seems simpler implementation at high level,
For pass multiple parameters, the work of the programmer in the control dimencion data type step, becomes more demanding.
In other cases, for some microprocessors architectures, the ANSI compilers customized, leveraged some of this old features to optimize the use of the code, forcing the location of these "untyped formal parameters" to work within or outside the work register, today you get almost the same with the use of "volatile" and "register".
But it should be noted that the most modern compilers,
not make any distinction between the two types of parameters declaration.
Examples of a compilation with gcc under linux:
In any case the statement of the prototype locally is of no use, because there is no call without parameters reference to this prototype will be remiss.
If you use the system with "untyped formal parameter", for an external call, proceed to generate a declarative prototype data type.
Like this:
int myfunc(int param);
Regarding parameter type, there are already correct answers here but if you want to hear it from the compiler you can try adding some flags (flags are almost always a good idea anyways).
compiling your program using gcc foo.c -Wextra I get:
foo.c: In function ‘func’:
foo.c:5:5: warning: type of ‘param’ defaults to ‘int’ [-Wmissing-parameter-type]
strangely -Wextra doesn't catch this for clang (it doesn't recognize -Wmissing-parameter-type for some reason, maybe for historical ones mentioned above) but -pedantic does:
foo.c:5:10: warning: parameter 'param' was not declared,
defaulting to type 'int' [-pedantic]
int func(param)
^
1 warning generated.
And for prototype issue as said again above int func() refers to arbitrary parameters unless you exclicitly define it as int func(void) which would then give you the errors as expected:
foo.c: In function ‘func’:
foo.c:6:1: error: number of arguments doesn’t match prototype
foo.c:3:5: error: prototype declaration
foo.c: In function ‘main’:
foo.c:12:5: error: too many arguments to function ‘func’
foo.c:5:5: note: declared here
or in clang as:
foo.c:5:5: error: conflicting types for 'func'
int func(param)
^
foo.c:3:5: note: previous declaration is here
int func(void);
^
foo.c:12:20: error: too many arguments to function call, expected 0, have 1
int bla = func(10);
~~~~ ^~
foo.c:3:1: note: 'func' declared here
int func(void);
^
2 errors generated.
If the function declaration has no parameters i.e. empty then it is taking unspecified number of arguments. If you want to make it take no arguments then change it to:
int func(void);
This is why I typically advise people to compile their code with:
cc -Wmissing-variable-declarations -Wstrict-variable-declarations -Wold-style-definition
These flags enforce a couple of things:
-Wmissing-variable-declarations: It is impossible to declare a non-static function without getting a prototype first. This makes it more likely that a prototype in a header file matches with the actual definition. Alternatively, it enforces that you add the static keyword to functions that don't need to be visible publicly.
-Wstrict-variable-declarations: The prototype must properly list the arguments.
-Wold-style-definition: The function definition itself must also properly list the arguments.
These flags are also used by default in a lot of Open Source projects. For example, FreeBSD has these flags enabled when building with WARNS=6 in your Makefile.
In the old-style declarator,
the identifier list must be absent unless
the declarator is used in the head of a function definition
(Par.A.10.1). No information about the types of the parameters is
supplied by the declaration. For example, the declaration
int f(), *fpi(), (*pfi)();
declares a function f returning an integer, a function fpi returning a pointer to an integer, >and a pointer pfi to a function returning an integer. In none of these are the parameter types >specified; they are old-style.
In the new-style declaration
int strcpy(char *dest, const char *source), rand(void);
strcpy is a
function returning int, with two arguments, the first a character
pointer, and the second a pointer to constant characters
SOURCE:- K&R book
I hope it cleared your doubt..
I've just come across someone's C code that I'm confused as to why it is compiling. There are two points I don't understand.
The function prototype has no parameters compared to the actual function definition.
The parameter in the function definition does not have a type.
#include <stdio.h>
int func();
int func(param)
{
return param;
}
int main()
{
int bla = func(10);
printf("%d", bla);
}
Why does this work?
I have tested it in a couple of compilers, and it works fine.
All the other answers are correct, but just for completion
A function is declared in the following manner:
return-type function-name(parameter-list,...) { body... }
return-type is the variable type that the function returns. This can not be an array type or a function type. If not given, then int
is assumed.
function-name is the name of the function.
parameter-list is the list of parameters that the function takes separated by commas. If no parameters are given, then the function
does not take any and should be defined with an empty set of
parenthesis or with the keyword void. If no variable type is in front
of a variable in the paramater list, then int is assumed. Arrays and
functions are not passed to functions, but are automatically converted
to pointers. If the list is terminated with an ellipsis (,...), then
there is no set number of parameters. Note: the header stdarg.h can be
used to access arguments when using an ellipsis.
And again for the sake of completeness. From C11 specification 6:11:6 (page: 179)
The use of function declarators with empty parentheses (not
prototype-format parameter type declarators) is an obsolescent
feature.
In C func() means that you can pass any number of arguments. If you want no arguments then you have to declare as func(void). The type you're passing to your function, if not specified defaults to int.
int func(); is an obsolescent function declaration from the days when there was no C standard, i.e. the days of K&R C (before 1989, the year the first "ANSI C" standard was published).
Remember that there were no prototypes in K&R C and the keyword void was not yet invented. All you could do was to tell the compiler about the return type of a function. The empty parameter list in K&R C means "an unspecified but fixed" number of arguments. Fixed means that you must call the function with the same number of args each time (as opposed to a variadic function like printf, where the number and type can vary for each call).
Many compilers will diagnose this construct; in particular gcc -Wstrict-prototypes will tell you "function declaration isn't a prototype", which is spot on, because it looks like a prototype (especially if you are poisoned by C++!), but isn't. It's an old style K&R C return type declaration.
Rule of thumb: Never leave an empty parameter list declaration empty, use int func(void) to be specific.
This turns the K&R return type declaration into a proper C89 prototype. Compilers are happy, developers are happy, static checkers are happy. Those mislead by^W^Wfond of C++ may cringe, though, because they need to type extra characters when they try to exercise their foreign language skills :-)
The empty parameter list means "any arguments", so the definition isn't wrong.
The missing type is assumed to be int.
I would consider any build that passes this to be lacking in configured warning/error level though, there's no point in being this allowing for actual code.
It's K&R style function declaration and definition. From C99 Standard (ISO/IEC 9899:TC3)
Section 6.7.5.3 Function Declarators (including prototypes)
An identifier list declares only the identifiers of the parameters of the function. An empty
list in a function declarator that is part of a definition of that function specifies that the
function has no parameters. The empty list in a function declarator that is not part of a
definition of that function specifies that no information about the number or types of the
parameters is supplied. (If both function types are "old style", parameter types are not compared.)
Section 6.11.6 Function declarators
The use of function declarators with empty parentheses (not prototype-format parameter
type declarators) is an obsolescent feature.
Section 6.11.7 Function definitions
The use of function definitions with separate parameter identifier and declaration lists
(not prototype-format parameter type and identifier declarators) is an obsolescent feature.
Which the old style means K&R style
Example:
Declaration: int old_style();
Definition:
int old_style(a, b)
int a;
int b;
{
/* something to do */
}
C assumes int if no type is given on function return type and parameter list. Only for this rule following weird things are possible.
A function definition looks like this.
int func(int param) { /* body */}
If its a prototype you write
int func(int param);
In prototype you can only specify the type of parameters. Parameters' name is not mandatory. So
int func(int);
Also if you dont specify parameter type but name int is assumed as type.
int func(param);
If you go farther, following works too.
func();
Compiler assumes int func() when you write func(). But dont put func() inside a function body. That'll be a function call
As stated #Krishnabhadra, all previous responses from other users, have a correct interpretation, and I just want to make a more detailed analysis of some points.
In the Old-C as in ANSI-C the "untyped formal parameter", take the dimencion of your work register or instruction depth capability (shadow registers or instruction cumulative cycle), in an 8bit MPU, will be an int16, in a 16bit MPU and so will be an int16 an so on, in the case 64bit architectures may choose to compile options like: -m32.
Although it seems simpler implementation at high level,
For pass multiple parameters, the work of the programmer in the control dimencion data type step, becomes more demanding.
In other cases, for some microprocessors architectures, the ANSI compilers customized, leveraged some of this old features to optimize the use of the code, forcing the location of these "untyped formal parameters" to work within or outside the work register, today you get almost the same with the use of "volatile" and "register".
But it should be noted that the most modern compilers,
not make any distinction between the two types of parameters declaration.
Examples of a compilation with gcc under linux:
In any case the statement of the prototype locally is of no use, because there is no call without parameters reference to this prototype will be remiss.
If you use the system with "untyped formal parameter", for an external call, proceed to generate a declarative prototype data type.
Like this:
int myfunc(int param);
Regarding parameter type, there are already correct answers here but if you want to hear it from the compiler you can try adding some flags (flags are almost always a good idea anyways).
compiling your program using gcc foo.c -Wextra I get:
foo.c: In function ‘func’:
foo.c:5:5: warning: type of ‘param’ defaults to ‘int’ [-Wmissing-parameter-type]
strangely -Wextra doesn't catch this for clang (it doesn't recognize -Wmissing-parameter-type for some reason, maybe for historical ones mentioned above) but -pedantic does:
foo.c:5:10: warning: parameter 'param' was not declared,
defaulting to type 'int' [-pedantic]
int func(param)
^
1 warning generated.
And for prototype issue as said again above int func() refers to arbitrary parameters unless you exclicitly define it as int func(void) which would then give you the errors as expected:
foo.c: In function ‘func’:
foo.c:6:1: error: number of arguments doesn’t match prototype
foo.c:3:5: error: prototype declaration
foo.c: In function ‘main’:
foo.c:12:5: error: too many arguments to function ‘func’
foo.c:5:5: note: declared here
or in clang as:
foo.c:5:5: error: conflicting types for 'func'
int func(param)
^
foo.c:3:5: note: previous declaration is here
int func(void);
^
foo.c:12:20: error: too many arguments to function call, expected 0, have 1
int bla = func(10);
~~~~ ^~
foo.c:3:1: note: 'func' declared here
int func(void);
^
2 errors generated.
If the function declaration has no parameters i.e. empty then it is taking unspecified number of arguments. If you want to make it take no arguments then change it to:
int func(void);
This is why I typically advise people to compile their code with:
cc -Wmissing-variable-declarations -Wstrict-variable-declarations -Wold-style-definition
These flags enforce a couple of things:
-Wmissing-variable-declarations: It is impossible to declare a non-static function without getting a prototype first. This makes it more likely that a prototype in a header file matches with the actual definition. Alternatively, it enforces that you add the static keyword to functions that don't need to be visible publicly.
-Wstrict-variable-declarations: The prototype must properly list the arguments.
-Wold-style-definition: The function definition itself must also properly list the arguments.
These flags are also used by default in a lot of Open Source projects. For example, FreeBSD has these flags enabled when building with WARNS=6 in your Makefile.
In the old-style declarator,
the identifier list must be absent unless
the declarator is used in the head of a function definition
(Par.A.10.1). No information about the types of the parameters is
supplied by the declaration. For example, the declaration
int f(), *fpi(), (*pfi)();
declares a function f returning an integer, a function fpi returning a pointer to an integer, >and a pointer pfi to a function returning an integer. In none of these are the parameter types >specified; they are old-style.
In the new-style declaration
int strcpy(char *dest, const char *source), rand(void);
strcpy is a
function returning int, with two arguments, the first a character
pointer, and the second a pointer to constant characters
SOURCE:- K&R book
I hope it cleared your doubt..