I'm working on a custom unit-testing framework that doesn't display the filename/line numbers of failed tests. I know I could require them as arguments for the report_results function but that seems like a lot of text.
Is there a way to make it so that __FILE__ and __LINE__ are always passed with the function, even if I don't pass them when I call it?
You can do something like this in C++:
void func(char *file=__FILE__, int line=__LINE__)(int more_args) {}
use a macro in your code, to call an underlying function
#define func(arg) real_func(__FILE__,__LINE__,arg)
where real_func is
void real_func(const char *file, int line, int arg);
In your code, when you call func(12), it expands to a call to real_func, with actual file path and line of the call. You can even support variable argument functions in C99 with variadic macros as a frontend.
Related
I wrote a function that that takes some argument and a pointer argument . when calling the function , sometimes I need to pass along the pointer for use inside the function and sometimes I don't .
what are the consequences of calling a function with fewer arguments ? it compiles correctly and during runtime its still fine , but is this good programming ? is it better if I call the function with a dummy variable ?
Thanks and sorry for beginner question .
If you call a function with too few arguments and the compiler doesn't complain, then you're doing something wrong.
You can write a function declaration/definition that doesn't specify how many arguments it requires:
void func();
/* ... */
func();
func(arg1);
func(arg1, arg2);
All three of those calls will be accepted by the compiler, but at least two of them are incorrect.
That form of function declaration/definition has been obsolescent since the 1989 ANSI C standard.
Never use this form.
Functions declaration should always be written as prototypes, i.e., declarations that specify the number and type(s) of the parameters. As a special case, (void) denotes a function with no parameters.
void func(int arg);
/* ... */
func(); /* rejected by compiler */
func(arg1); /* accepted -- but only if arg1 is of type int or convertible to int */
func(arg1, arg2); /* rejected by compiler */
If you manage to write code that calls a function with an incorrect number of arguments and get it past the compiler, the behavior is undefined. It might appear to "work", but it could blow up in your face when, for example, you compile it with a different compiler, or with the same compiler and different options.
One complication: some functions are variadic, taking a variable number of arguments. The most common example of this is printf. For variadic functions, the required arguments are typically specified by the function's documentation -- and it's just as important to get the arguments right. The difference is that, for variadic functions, your compiler won't necessarily tell you that a call is incorrect.
The , ... syntax (in the function declaration) and the macros defined in <stdarg.h> are the only legitimate way to write and use C functions that take a variable number and type(s) of arguments.
One of the differences of C++ over plain C is that it incorporates name mangling, which lets you specify a single function with varying return types and parameters. Two functions that share the same name but have different parameters:
int foo();
int foo(int param1, char* param2);
can be done in C++ because it actually alters the name of functions behind-the scenes as it compiles it. When you want to pass in a different number of parameters, it's essentially the same as having two different function names that it calls:
int foo1();
int foo2(int param1, char* param2);
When you pass in fewer parameters than it expects, some compilers should at least throw warnings; others won't even compile the program at all.
Let's say that you pass in 2 parameters to a function that expects 3. When you try to reference that 3rd parameter within your function, what do you expect the value to be? Most of the time, it will be a garbage value, and definitely something your function does not expect.
I would suggest just passing in a dummy value to functions like that: a NULL for a pointer or a 0 or negative "uninitialized" kind of value for other types. You can at least test for those values in your function. Or just write a second function that takes a different number of parameters.
I would not do this. I would only call the function with the declared number of arguments.
It is extremely confusing to the reader of the code.
The reader of the code might even think the function has been overloaded and look
for the other definitions of the function with fewer arguments.
The omitted arguments can have any value at all - anything is considered legal behavior by the C compiler. The program may work perfectly in a test environment and then crash for any or no reason.
If I absolutely had to have a variable number of arguments, for a legitimate purpose, I would try to put the arguments in a list instead of using a variable number of arguments. If someone else required me to use variable arguments, I would use varargs instead of the default behavior, and then only in the case where all the arguments are the same type.
Recently I got a question when writing a program for file opening.
Let me explain my question clearly. Here I'm taking open call as an example.
To create a file:
open("file_name", O_CREAT, 0766); //passing 3 parametrs
To open a file:
open("file_name", O_RDWR); //only 2 arguments.
Then I clearly observed this point and it also works for main() too.
main(void) //worked
main(int argc, char **argv); //worked
main(int argc) //worked and it's doesn't give an error like "too few arguments".
main() //worked
So how we can create these optional arguments? How exactly can the compiler validate these prototypes? If possible, please write an example program.
The open function is declared as a variadic function. It will look something like this:
#include <stdarg.h>
int open(char const * filename, int flags, ...)
{
va_list ap;
va_start(ap, flags);
if (flags & O_CREAT)
{
int mode = va_arg(ap, int);
// ...
}
// ...
va_end(ap);
}
The further arguments are not consumed unless you have indicated that they do in fact exist.
The same construction is used for printf.
The manual doesn't always make this explicit, since the only possible two signatures are (char const *, int) and (char const *, int, int), so there's little point in revealing that you the function actually accepts variable arguments. (You can test this by trying to compile something like open("", 1, 2, 3, 4, 5, 6).)
In all cases, a varargs function must be able to determine somehow, from the fixed arguments, how many variable arguments there are. For example, the printf() family of functions use the format string to determine the number and types of the arguments. The execl() function uses a sentinel (null pointer) to mark the end of the argument list. It would be possible to use a count instead of a sentinel (but if you're going to do that, the chances are that a count and an array in a non-varargs function would work as well as, if not better than, a count and a list of arguments). The open() function uses one of the flag bits to determine whether the mode should be present — see Kerrek SB's answer.
The main() function is a special case. The implementation (compiler) is prohibited from declaring a prototype for it, and must accept at least the two forms:
int main(int argc, char **argv);
int main(void);
or their equivalents. It may accept other forms too; see What's the use of the third environment variable in the C main()? for one common form. In C, but not C++, a standard compiler can document other return types — and Microsoft has documented void as a valid return type from VS 2008 onwards.
Because there is no implementation-provided prototype for main(), the compiler can't officially reject any declarations/definitions of main(), though it might pass comment on forms it doesn't recognize (GCC does comment on main() functions that do not return an int type, for example).
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.
Related to [question]: How do you pass a function as a parameter in C?
Is it possible in C to pass a function that has a variable number of arguments to another function? If so, could someone point me to some documentation or fill me in? Thanks.
You can't pass a function (of any sort) as a parameter, but you can pass a pointer to a function (again, of pretty much any sort). It's usually easiest to use a typedef:
typedef int (*fptr)(char const *, ...); // e.g., match with `printf`
int apply(fptr f, char const *a, int b) {
return f(a, b);
}
You can make a function pointer, e.g.:
typedef int (*vafunc)(const char *, ...); // like printf
However, you cannot really forward the arguments, i.e. the following doesn't exist in standard C:
void call_other(vafunc f, const char * fmt, ...)
{
// want to say:
// f(fmt, ...); // How to write this???
}
GCC offers such anonymous argument forwarding as an extension, but it's not possible in standard C. You're typically expected to match each variadic function with a v... counterpart that takes a va_list argument, precisely for this purpose. (Calling f with a fixed number of arguments is possible, of course: f("abc", 1, 2, 3);)
http://www.lemoda.net/c/function-pointer-ellipsis/index.html seems to be what you seek.
You can pass a varargs function the same way as you would another function.
Here's a short test program that demonstrates passing a varargs function as a parameter:
int bar(int x, ...) {
/* In a real program, you would actually use the arguments beyond x */
return x;
}
int foo(int (*baz)(int, ...)) {
return bar(10, "ABC");
}
int main(void) {
printf("%d\n", foo(bar));
return 0;
}
It prints 10, as you might expect.
N.B. You can't actually pass a function as an argument to another function in C - instead, you can pass a function pointer, which points to the actual function as loaded from the executable. This is weaker than the first-class status of functions in functional programming languages, or even than the status of a delegate in some object-oriented languages like C#. For instance, you can't create a function on the fly in C.
Sure. They're called "variadic functions".
1) Just use an "ellipses" ("...") as the last argument in your function prototype
2) In order for the called function to "know" how many arguments were passed to it, use the macros "va_start" and friends in "stdargs":
3) 1) and 2) above are simply to have a function that has a variable #/arguments. You can also have a function pointer with a variable #/arguments. Do the same thing - just include the ellipses ("...") in your function prototype, and use "stdargs" in your function implementation.
My library offers a callback point where my library users can register to get information. The general form of the callback is an int followed by various parameters whose type depend on the int value. Therefore, I defined the callback type and the function to set it as follows.
typedef void (* callback_func_t)(int type, ...);
void set_callback_func(callback_func_t callback);
Within my library, I am calling this function all throughout, being the user set function, or the default one I am providing. It works.
Now, I'd like to add a level of indirection, to be able to call several registered callbacks. The trouble is that my internal callback function that still takes ellipsis parameters, also have to call the callback function with ellipsis. As a consequence, my internal function has to interpret the type, unpack the parameters from the va_list and give them as parameters to the callbacj function.
void internal_callback(int type, ...) {
va_list args;
va_start(args, type);
switch (type) {
case 0: call_callback(type, va_arg(args, int)); break;
// ...
}
va_end(args);
}
But then, in the user's implementation of the callback, there will also be the same va_list usage, and interpretation of the arguments, according to the value of type. The solution is to pass directly the va_list as an argument to the callback function, making the implementation of the internal callback function obvious.
typedef void (* callback_func_t)(int type, va_list args);
My question is: is it good practice to define a callback function type that takes va_list as argument? I can define my callback function type as above, but what are the pros and cons compared to the definition at the top?
I assume there is a finite and known number of types? If so, why not use enumerations and unions for some level of type safety, which would incidentally also solve your problem:
enum callback_arg_type { INT_ARG, DOUBLE_ARG, VECTOR_ARG };
union callback_arg
{
int as_int;
double as_double;
struct { double x, y, z; } as_vector;
};
typedef void (*callback_func_t)(
enum callback_arg_type type, union callback_arg arg);
Depending on the difference of argument sizes, it might be a good idea to pass a pointer instead. You could also provide some macros to provide a nicer syntax for callback invocation, but if they are only ever called from within your library, it might not be worth it:
union callback_arg arg = { .as_int = 42 };
callback_fn(INT_ARG, arg);
is pretty short on its own.
I would go with the va_list version. The user is already dealing with the scariness of dealing with va_lists so you don't save anything by hiding that from them.
Additionally using the list rather than trying to repass the arguments will cut down on stack usage. If you had to repass the arguments to their function it would make a new copy of all of those arguments, but passing the va_list type will just use the instance of those arguments already on the stack.
Finally, your code will both be simpler (if I'm understanding the problem correctly) and you will save each user from having to call va_start and va_end (which probably won't change the output code in their function much for most implementations of stdarg) but otherwise they all have to type those calls and (depending on how stdargs are implemented on the platform) they will need to make sure they actually do call va_end before returning (easy to miss if returning early in case of an error).