I'm confused about why we need to pass void into C functions:
int f(void) { return 0; }
versus
int f() { return 0; }
What is the proper thing to do and why?
In C, int f() is an old-style declaration. It says that f expects a fixed but unspecified number and type(s) of arguments. For example, given int f() { return 0; }, the compiler won't complain about f(42), or f("hello, world") (though the behavior of such a call is undefined).
int f(void) explicitly says that f takes no arguments.
(C++ has different rules; Stroustrup wasn't as concerned about backward compatibility with old C code.)
It's a vestige of C.
f(void) takes no arguments, so f(1) is invalid.
f() means that the parameters are unspecified, so f(1) is valid here.
The void in this case just means "there are no parameters." I'm not sure whether your second case will compile, but either way I'd prefer the first case just to be as clear as possible. Of course, when calling f, you just use the empty parentheses:
int x = f();
Related
I don't know if it's possible but the wikipedia article here Compatibility of C and C++ says the following :
In C, a function prototype without arguments, e.g. int foo();,
implies that the parameters are unspecified. Therefore, it is legal to
call such a function with one or more arguments, e.g. foo(42, "hello
world").
In contrast, in C++ a function prototype without arguments
means that the function takes no arguments, and calling such a
function with arguments is ill-formed.
In C, the correct way to
declare a function that takes no arguments is by using void, as in
int foo(void);.
I made the following code to test it and catch the passed variables (which doesn't work quite right)
#include<stdio.h>
#include<stdarg.h>
void foo();
int main()
{
int i = 3;
foo(i);
return 0;
}
void foo()
{
// va_list args;
// va_start(args);
//
// int x = va_arg (args, int);
// printf("%d", x);
// va_end(args);
}
Is it possible to catch the passed i or is Wikipedia talking about something completely different?
You can't, at least not in standard C. What the Wikipedia article means is this code:
void foo();
int main()
{
int i = 3;
foo(i);
return 0;
}
void foo(int i)
{
(void)i;
}
Compiles fine in C, but it's invalid in C++ because the number of arguments don't match.
If you read the documentation for va_start you will see that it needs the last "real" argument in the argument list. So it's not possible in plain C to get the arguments if you don't declare any arguments.
What you can do is to declare the function prototype without arguments, and have arguments in the actual definition.
That comes from the old C days when the strictness of the language was, well..., relaxed.
The basic idea was that if you had a function in a translation unit, say foo.c:
float foo(int x)
{
return 2.0F * x;
}
And then you want to use it in another translation unit, say main.c but you don't want to bother with writing a header file, you could just do:
int main()
{
float foo();
float r;
r = foo(42);
}
And you don't have to write the arguments of the function. To be fair, you didn't have to write the prototype at all, but then the compiler would assume that the function always returns int which may not be what you need.
Then, as the language matured, this kind of function declaration was decided to be a very bad idea, so generally speaking you should not (try to) use it. If you want a variadic function, then by all means use it, but declare it as such. And you have to give it at least a real argument, to anchor the call to va_start().
You can call the function with any arguments, but you can't access them in the function scope. Anyway some compilers will give you warnings if you don't declare the prototype as int foo (void); since you probably don't want to do this anyway.
There is a way to access those parameters in C program, but I look at it as a big hack, which should be avoided.
Next example shows how to access an int parameter :
#include<stdio.h>
#include<stdarg.h>
void foo();
int main()
{
int i = 3;
foo(i);
return 0;
}
void foo(int p)
{
printf("%d",p);
}
Now, I am not sure what happens if you pass something else then int (for example char*), but it may cause an undefined behavior.
In c++ (as said), you can not pass parameters to functions taking no parameters.
This question already has answers here:
Alternative (K&R) C syntax for function declaration versus prototypes
(5 answers)
Closed 6 years ago.
What are the differences between a K&R function declaration and an ANSI function declaration?
K&R syntax is obsolete, you can skip it unless you have to maintain very old code.
// K&R syntax
int foo(a, p)
int a;
char *p;
{
return 0;
}
// ANSI syntax
int foo(int a, char *p)
{
return 0;
}
Legacy K&R-Style Declarations/Definitions
When Kernighan and Ritchie first published "The C Programming Language", C didn't yet offer full function prototypes. Forward declarations of functions existed, but with the sole purpose of indicating a return type. For functions that returned int, they weren't required until C99.
By C89, the notion of a function prototype, which also specifies the types of the parameters (and, implicitly, their number) had been added. Since a prototype is also a type of function declaration, the unofficial term "K&R function declaration" is sometimes used for a function declaration that is not also a prototype.
// K&R declarations, we don't know whether these functions have parameters.
int foo(); // this declaration not strictly necessary until C99, because it returns int
float bar();
// Full prototypes, specifying the number and types of parameters
int foo(int);
float bar(int, float);
// K&R definition of a function
int foo(a)
int a; // parameter types were declared separately
{
// ...
return 0;
}
// Modern definition of a function
float bar(int a, float b)
{
// ...
return 0.0;
}
The Accidental K&R Declaration
It's worth noting that newcomers to C may accidentally use K&R declarations when they intend to use a full prototype, because they may not realize that an empty parameter list must be specified as void.
If you declare and define a function as
// Accidental K&R declaration
int baz(); // May be called with any possible set of parameters
// Definition
int baz() // No actual parameters means undefined behavior if called with parameters.
// Missing "void" in the parameter list of a definition is undesirable but not
// strictly an error, no parameters in a definition does mean no parameters;
// still, it's better to be in the habit of consistently using "void" for empty
// parameter lists in C, so we don't forget when writing prototypes.
{
// ...
return 0;
}
...then you have not actually given a prototype for a function that takes no parameters, but a declaration in K&R-style for a function that accepts an unknown number of parameters of unknown type.
AnT notes in this answer to a similar question that this syntax is deprecated but still legal as of C99 (and that function pointers to functions with unknown number and type of parameters still have potential applications, though at high risk of undefined behavior); as such, compliant compilers will, at best, produce a warning if a function is declared or called without a proper prototype.
Calling functions without prototypes is less safe, because the compiler cannot verify that you have passed the correct number and types of parameters in the correct order; undefined behavior results if the call is not actually correct.
The correct way to declare and define a parameterless function is, of course:
// Modern declaration of a parameterless function.
int qux(void); // "void" as a parameter type means there are no parameters.
// Without using "void", this would be a K&R declaration.
// Modern definition of a parameterless function
int qux(void)
{
// ...
return 0;
}
I just want to add that in the traditional K & R style type modifiers for functions that return an int value aren't even necessary.
Consider the modern C11 notation of a simple HelloWorld program:
int main(int argc, char **argv) {
printf("hello world\n");
return 0;
}
This is equivalent to the K & R notation style:
main(argc, argv)
int argc;
char **argv;
{
printf("hello world\n");
return 0;
}
Note that the int before main() is ignored, but the code still compiles. That's a part of the K & R definition.
Quote Wikipedia:
In early versions of C, only functions that returned a non-int value needed to be declared if used before the function definition; a function used without any previous declaration was assumed to return type int, if its value was used.
--source: https://en.wikipedia.org/wiki/C_(programming_language)#K.26R_C
This is arguably a legacy coding-style and should be avoided due to clarity issues, but quite often old algorithm textbooks favour this sort of K & R style.
I don't understand why the following code generates a warning:
int func(double a, int b, char c)
{
return 0;
}
int main()
{
int(*myPointer)() = func;
return 0;
}
I thought that in C, a function with an empty parameters list mean a function that can receive an unknown number of parameters. func4 happens to receive 3 parameters. So why is it incompatible with myPointer?
Its especially confusing because the following does compile without warning:
void boo()
{
return;
}
int main()
{
int(*pointerDude)(double) = boo;
return 0;
}
What's going on?
The difference between the two cases is explained like this: if you pass a parameter to a function that accepts none, you are just consuming some memory on the stack. If you don't pass any parameter to a function that accepts a few, the latter is going to read random data from the stack.
Update: changed to community wiki to add these corrections from Pascal Cuoq:
Casts of function pointer in both directions are legal, informative warnings from the compiler notwithstanding. Calling a function with the wrong prototype is illegal in both cases. Some ABIs mandate that the function clean up the stack, in which case passing parameters to functions that accept none corrupt the stack as surely as not passing parameters to functions that expect them.
C99 6.3.2.3 par. 8:
A pointer to a function of one type may be converted to a pointer to a
function of another type and back again; the result shall compare
equal to the original pointer. If a converted pointer is used to call
a function whose type is not compatible with the pointed-to type, the
behavior is undefined
This is the warning you get:
warning: initialization from incompatible pointer type
You are passing void which means that will require a cast. You should use the right types.
IIRC C compiler has certain assumptions which can cause very odd bugs because you're not telling it how much stack space it needs whenever that function is called. Especially since the definitions don't match this might allow someone to inadvertently read your function pointer declaration and assume no parameters and have the function return garbage. If you really want to take variable numbers of parameters use my_func(...) and varargs.
A warning is just that, a warning. Honest.
In that case, the compiler knows you have an incorrect function pointer type and it blatantly tells you that. If you try to pass a number of parameters different then 3, then it will be issued an error.
I think that the problem is related to the casting of the parameters, because char is not 32 bits. Note that if you change the char to int this works fine. It is related to automatic promotion of variables.
Compare the two:
int func();
int func(double a, int b, int c)
{
return 0;
}
and
int func();
int func(double a, int b, char c)
{
return 0;
}
gcc gives you warning for the second, but not for the first
In C an empty parameter list means that the function does not take any parameters. I believe you are confusing an empty parameter list with varargs.
Changing your first example to include the parameters will remove the warning.
int func(double a, int b, char c)
{
return 0;
}
int main()
{
int(*myPointer)(double, int, char) = func;
return 0;
}
This question already has answers here:
Alternative (K&R) C syntax for function declaration versus prototypes
(5 answers)
Closed 6 years ago.
What are the differences between a K&R function declaration and an ANSI function declaration?
K&R syntax is obsolete, you can skip it unless you have to maintain very old code.
// K&R syntax
int foo(a, p)
int a;
char *p;
{
return 0;
}
// ANSI syntax
int foo(int a, char *p)
{
return 0;
}
Legacy K&R-Style Declarations/Definitions
When Kernighan and Ritchie first published "The C Programming Language", C didn't yet offer full function prototypes. Forward declarations of functions existed, but with the sole purpose of indicating a return type. For functions that returned int, they weren't required until C99.
By C89, the notion of a function prototype, which also specifies the types of the parameters (and, implicitly, their number) had been added. Since a prototype is also a type of function declaration, the unofficial term "K&R function declaration" is sometimes used for a function declaration that is not also a prototype.
// K&R declarations, we don't know whether these functions have parameters.
int foo(); // this declaration not strictly necessary until C99, because it returns int
float bar();
// Full prototypes, specifying the number and types of parameters
int foo(int);
float bar(int, float);
// K&R definition of a function
int foo(a)
int a; // parameter types were declared separately
{
// ...
return 0;
}
// Modern definition of a function
float bar(int a, float b)
{
// ...
return 0.0;
}
The Accidental K&R Declaration
It's worth noting that newcomers to C may accidentally use K&R declarations when they intend to use a full prototype, because they may not realize that an empty parameter list must be specified as void.
If you declare and define a function as
// Accidental K&R declaration
int baz(); // May be called with any possible set of parameters
// Definition
int baz() // No actual parameters means undefined behavior if called with parameters.
// Missing "void" in the parameter list of a definition is undesirable but not
// strictly an error, no parameters in a definition does mean no parameters;
// still, it's better to be in the habit of consistently using "void" for empty
// parameter lists in C, so we don't forget when writing prototypes.
{
// ...
return 0;
}
...then you have not actually given a prototype for a function that takes no parameters, but a declaration in K&R-style for a function that accepts an unknown number of parameters of unknown type.
AnT notes in this answer to a similar question that this syntax is deprecated but still legal as of C99 (and that function pointers to functions with unknown number and type of parameters still have potential applications, though at high risk of undefined behavior); as such, compliant compilers will, at best, produce a warning if a function is declared or called without a proper prototype.
Calling functions without prototypes is less safe, because the compiler cannot verify that you have passed the correct number and types of parameters in the correct order; undefined behavior results if the call is not actually correct.
The correct way to declare and define a parameterless function is, of course:
// Modern declaration of a parameterless function.
int qux(void); // "void" as a parameter type means there are no parameters.
// Without using "void", this would be a K&R declaration.
// Modern definition of a parameterless function
int qux(void)
{
// ...
return 0;
}
I just want to add that in the traditional K & R style type modifiers for functions that return an int value aren't even necessary.
Consider the modern C11 notation of a simple HelloWorld program:
int main(int argc, char **argv) {
printf("hello world\n");
return 0;
}
This is equivalent to the K & R notation style:
main(argc, argv)
int argc;
char **argv;
{
printf("hello world\n");
return 0;
}
Note that the int before main() is ignored, but the code still compiles. That's a part of the K & R definition.
Quote Wikipedia:
In early versions of C, only functions that returned a non-int value needed to be declared if used before the function definition; a function used without any previous declaration was assumed to return type int, if its value was used.
--source: https://en.wikipedia.org/wiki/C_(programming_language)#K.26R_C
This is arguably a legacy coding-style and should be avoided due to clarity issues, but quite often old algorithm textbooks favour this sort of K & R style.
I forgot to write void parameter but it works the i put void it gives error
it lets this:
print(int size,int table[size][size]){
int i,j;
printf("-------TABLE-------\n");
for(i = 0;i<size;i++){
for(j = 0;j<size;j++){
if(table[i][j]==EMPTY)
printf(". ");
else
printf("* ");
}
printf("\n");
}
}
it says"previos implicit declaration was here " (means the call in main)
void print(int size,int table[size][size]){
int i,j;
printf("-------TABLE-------\n");
for(i = 0;i<size;i++){
for(j = 0;j<size;j++){
if(table[i][j]==EMPTY)
printf(". ");
else
printf("* ");
}
printf("\n");
}
}
If you declare a function
foo(int x) {
}
the compiler will infer the return-type to be int, as if you had written
int foo(int x) {
}
But, really, that's the least of your problems.
Reference: ยง1.3.1 of The C Library Reference Guide by E. Huss
It's a historical artifact. This happens for backwards compatibility with old C code (from before C was standardized). Functions without explicit return types are assumed to return int, and if no explicit parameters are specified, it's assumed to take some unspecified number of arguments.
In C, in contrast to C++, and assuming you are not using a strict C99 conformance mode in your compiler, then when the compiler comes across something that looks like a function call but the identifier has not previously been declared, then the compiler assumes that it is the name of a function returning an integer.
int main(void)
{
something_functional(1, 2);
}
Without a prototype, the compiler in C90 or relaxed C99 mode will assume that 'something_functional()' is indeed a function returning an integer.
If you subsequently write:
something_functional(double d, char *s)
{
...
}
The compiler will assume that the return type of 'something_functional()' is an int and will let the code compile (despite the horrendous mismatch between the actual argument types in the call and in the function definition).
If you subsequently write:
void something_functional(douebl d, char *s)
{
...
}
the compiler will, quite correctly, complain that you've told it different things about the function and that makes it erroneous.
There are several ways to fix the problem:
Move the function definition ahead of the function call. This is what Pascal required, and leads to the main() function appearing at the bottom of the file.
Place a prototype for the function ahead of its use in the file:
static void something_functional(double d, char *s);
I take the view that if the function is not going to be called from outside the source file, it should be static.
Note that C99 in a strict conforming mode does not allow you to declare functions implicitly. C++ never has either.
There's another interesting feature of pre-C99. You could also write:
static c;
static function();
some_function(a, b)
{
}
This defines an integer variable c, a function called function() that returns an int, and a function called some_function() that takes two int arguments and returns an int.
This is not allowed in strict C99 code - and was not particularly good style in C90 code, but was allowed for backwards compatibility with pre-standard C.
without void eg, function() says the function declaration might have any parameters.
function(void) says that it has precisely none.