Calling of C functions with undefined number of parameters - c

Note this question does not refer to ellipsis.
Consider the following code
#include <stdio.h>
void foo() {
printf("I AM AWESOME\n");
}
main(void) {
foo(1,2,3);
foo();
return 0;
}
This program runs perfectly and provides the output.
However, in case of 'main', this works irrespective of
main(void)
or
main()
When, defining foo as
foo(void)
gives an error - "too many arguments".
If both are functions, shouldn't they also follow the same rules?

When you declare a function without parameters it means to disable type checking and to use K&R calling convention. It does not mean that the function does not have parameters.
In ANSI when you want to explicitly say that the function does not have parameters, you need to declare it as fun(void).

the is also somethg else in C called variable number of arguments
void foo(int x, ...)
https://www.geeksforgeeks.org/variable-length-argument-c/

The foo(void) takes no arguments (!!!), whereas foo() takes an unspecified number of arguments!

Related

Passing variables between functions in c with out using global variables

I am trying to print the value of a local variable inside of main, from another function without using global variables. What would be the best way to do so?
#include <stdio.h>
int function1();
int main(void) {
int hello=10;
printf(function1());
}
int function1(int ip){
printf("hello%d",ip);
}
I am expecting the 10 to be printed next to the "hello" but instead get a 0.
You need to call the function passing the value (or variable) required.
int function1(int);
int main(void)
{
int hello=10;
function1(hello);
function1(130);
}
int function1(int ip)
{
return printf("hello - %d\n",ip);
}
https://godbolt.org/z/97o3dPWzj
change
int function1();
to
int function1(int);
and
printf(function1());
to
function1(hello);
"I am expecting the 10 to be printed next to the "hello" but instead get a 0."
There are already examples of working versions of your code in the other answers, but little is said in the way of explanation. I will try to do that here, and offer some general suggestions.
Although your code compiles, it does so with warnings and when run, produces run-time errors. The information resulting from both of these, if heeded would likely provide a guide to addressing most of your issues. (If using GCC for example, you can set warnings to -Wall). To illustrate, here is an image showing line numbers and the warning that correspond with them on my system (not GCC, but warning are turned on)
Build warnings:
And finally, run-time error:
From these you can begin to derive some of the following observations (others listed are my own.)
The signature of a function prototype must match its implementation. (for function1, they do not)
If the prototype of a function is non-void, then it should return a value.
If a function returns a value, its return value should not be ignored.
The warning of an unused variable pointed out that you probably intended to use it as an argument here: function1()
See comments below for other clarifications:
int function1();//this prototype is incomplete, and is inconsistent
//with the signature of its implementation
int main(void) {
int hello=10;
printf(function1());//because function1 is not returning a value, your code outputs a 0
//Function1 prototype requires it to pass an argument
// non-void function should return a value here
}
int function1(int ip){//signature of this implementation disagrees with its prototype
//because there is no value passed, ip can be any value
printf("hello%d",ip);
// non-void function should return a value here
}

Function of main() in C programming

I am working in the C programming language. What is the function of main()? What is void main() and int main()?
It is the entry point of a C program. See here:
https://en.wikipedia.org/wiki/Entry_point#C_and_C++
Best answer of Brian-Bi:
void main() { ... } is wrong. If you're declaring main this way, stop. (Unless your code is running in a freestanding environment, in
which case it could theoretically be correct.)
main() { ... } is acceptable in C89; the return type, which is not specified, defaults to int. However, this is no longer allowed in
C99. Therefore...
int main() { ... } is the best way to write main if you don't care about the program arguments. If you care about program arguments,
you need to declare the argc and argv parameters too. You should
always define main in this way. Omitting the return type offers no
advantage in C89 and will break your code in C99.
What is the function of main()?
It is the entry point of your program. That's the first function which is executed when you run your program.
What is the difference between void main() and int main()?
The valid syntax for the main() function is:
int main(void)
It can also take arguments. See more here.
The second syntax is not valid:
void main(void)
That's because your main() should return the exit status of your program.

Catching variables passed to function with no arguments

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.

int foo (int argc, ...) vs int foo() vs int foo(void) in C

So today I figured (for the first time admittedly) that int foo() is in fact different from int foo(void) in that the first one allows any number of inputs and the second one allows zero.
Does int foo() simply ignore any given inputs? If so, what's the point of allowing this form of function? If not, how can you access them and how is this different from having a variable argument list (e.g. something like int foo (int argc, ...))?
The key to understanding this is understanding the call stack. What happens when you call a function in C (with the standard x86 ABI — other platforms may vary) is that the caller pushes all of the arguments, in reverse order, onto the stack before calling the callee. Then, the callee can read as many of those arguments as it wants. If you use foo(void), obviously you won't read any. If you use foo(int), you'll be able to read one word into the stack below your current frame.
Using foo() (with no args specified) means that the compiler won't care to check the arguments you pass to foo. Anything goes; there's no contract. This can be useful if foo has two different implementations that take different types as arguments, and I want to be able to switch them out programmatically. (It's also sometimes useful when writing functions in assembler, where you can handle the stack and arguments yourself.) But remember that the compiler is not going to do any type-checking for you, so you have to be very careful.
This is different from foo(int, ...), since in that case, the function actually has a way to access all of the arguments (using varargs). There's no reason ever to actually define a function with foo(), since it's basically equivalent to foo(void). foo() is only useful for declarations.
First, take int foo(). This form is a function declaration that does not provide a prototype - that is, it doesn't specify the number and types of its arguments. It is an archaic form of function declaration - it's how functions were originally declared in pre-ANSI C. Such a function however does have a fixed number and type of arguments - it's just that the declaration doesn't tell the compiler what it is, so you are responsible for getting it right where you call the function. You declare such a function with arguments like so:
int foo(a, b)
int a;
char *b;
{
return a + strlen(b);
}
This form of function declaration is now obsolete.
int foo(void) is a modern declaration that provides a prototype; it declares a function that takes no arguments. int foo(int argc, ...) also provides a prototype; it declares a function that has one fixed integer argument and a variable argument list.
In standard conform C, you have to use int foo(void) if the function does not accept any parameters.
I guess it is compiler dependant what happens, when you pass arguments to a function with empty braces. But I don't think there is a way to access these parameters.
As for main, the only standard conform (pure c) ways to write them are either int main(void) or int main(int argc, char **argv) (or char *argv[] which is the same).
Well, in C++ the two forms are equivalent and they both declare a function that takes no arguments. If you try to call the function and pass in an argument, the compile will give an error.
On the other hand, C and Objective-C both treat the two forms differently. In these languages the first form declares a function that takes an unknown number of arguments, whereas the second form declares a function that takes no arguments at all. So, in C the following is valid code:
int foo() {
return 5;
}
int main() {
return foo(1, 2, 3);
}
The compiler doesn't complain, and the code runs fine (a C++ compiler would give an error on this same code).
Generally what you want in C and Objective-C is to use the second form and include the explicit void to indicate that the function should take no arguments. However, it's more common in C++ to use the first form because it's equivalent and shorter.

How to implement a "private/restricted" function in C?

I was asked a very interesting question during a C interview: How can you implement a function f() in such a way that it can only be called from a particular g() function. If a function other than g() tries to call f() it would result in a compiler error.
At first, I though this could be done with function pointers and I could get close to blocking the call at runtime. But I was not able to think of a compile time strategy. I don't even know if this is possible using ansi C.
Does anyone have any idea?
Here's one way:
int f_real_name(void)
{
...
}
#define f f_real_name
int g(void)
{
// call f()
}
#undef f
// calling f() now won't work
Another way, if you can guarantee that f() and g() are the only functions in the file, is to declare f() as static.
EDIT: Another macro trick to cause compiler errors:
static int f(void) // static works for other files
{
...
}
int g(void)
{
// call f()
}
#define f call function
// f() certainly produces compiler errors here
Put g() and f() in the same module, and declare f() as static. The static keyword makes f() available only to functions in the same module, or source file.
You might also want to mention that no other methods should be allowed in the module with f() and g(), otherwise they could call f().
PS - I really think Chris Lutz' answer is actually the best. It mentions this approach, but also a clever macro renaming that works with fewer environmental conditions (does not require the module file specifically for these two functions).
Note also that with a macro, you could do the following:
#define f() f_should_not_be_called_by_anything_except_g
Which would present a nice error message, and auto-completers (like Visual Studio) would show that tip when the user types f().
You can make module-private functions with the static keyword:
static void func(void)
{
// ...
}
Then, func() can only be called by other functions defined in the same file (technically, the same translation unit: other functions whose definitions are included by a #include directive can still access it). func is said to have internal linkage. All other functions (that is, without the static keyword) are said to have external linkage.
Beyond that, no, there is no way to make functions inaccessible. You can use macros to change the name of the function, but other code can always still access it with the appropriate name.
Place f() and g() in the same source file, declare f() static.
An option for GCC is to use nested functions. While it's not standard C, it works quite well.
It is only possible coincidentally.
If functions f() and g() are both in the same source file, and there are no other functions in the file, and if g() never returns the function pointer to f() to any of its callers, then making f() static will do the job.
If other functions must appear in the same source file, placing f() at the bottom of the file as a static function, and only defining g() immediately after it would achieve more or less the same effect - though if you didn't tell the compiler to generate errors on 'missing declarations' other functions could call it with warnings.
#include <stdio.h>
extern void g(void); /* in a header */
/* Other functions that may not call f() go here */
static void f(void)
{
puts("X");
}
void g(void)
{
f();
}
Clearly, this technique cannot be extended reliably to another pair of functions in the same file - x() and y() - such that x() and only x() can call y() while g() and only g() can call f() at the same time.
However, normally you would rely on the programmers' discipline and simply make f() static in the source file, along with a comment that only g() may call it, and then discipline anyone who modifies the code so that a function other than g() calls f().
You could implement f() as a macro and let the pre-compiler handle it:
#include <stdio.h>
#define f(s) printf("Hello %s!\n", s);
void g(char * w) {
f(w);
}
#undef f
int main(void) {
/* f() calls will produce an undefined reference to 'f' linker error */
g("World");
return(0);
}
In this way, there is no other exposed function and no need for a static function.

Resources