How does Variable Length Argument lists functions like printf() , scanf(), etc in C differ from Function Overloading in C++?
And how does the call
printf("Didnt Work %s",s);
differ from
printf(s,"Didnt Work %s");
where s is defined as:
const char *s="string";
Please Explain.
In
const char *s="string";
printf(s,"Didnt Work %s");
The first argument "string" is interpreted as the format string. It has no insertion codes, so the second parameter won't ever be used. The result will be "string".
OTOH
printf("Didnt Work %s",s);
There is an insertion code, so the second argument gets inserted as a string, the result is "Didn't Work string".
This isn't overloading, because although different argument types are possible just as in overloading, with variable arguments the same function is always called. With overloading different functions are called depending on the argument types.
To answer your second question, others have already for the first.
Variable argument lists in C are very different from overloading in C++. In C you have one function printf that does perhaps different things with different types of arguments. In C++, with overloading you choose between different functions according to the type of the argument.
Overloading allows for a specific ordering of parameters that the compiler will check for. In C++, if the types don't match for at least one of the function definitions, the compiler will complain. On the other hand, C with variable length arguments, ..., doesn't have this type checking at compile time. The compiler doesn't check any of the parameters to make sure they lined up. you can compile printf("1",3); on most if not all compilers. Printf will try to read the first argument as a string and will keep reading until it reaches an empty byte signifying the end of a string. This is why variable length argument lists are discouraged.
Related
I ran across this example in Stroustrup's "A Tour of C++" (2014). If you define functions with the exact same name but different argument types, the compiler will select the most appropriate function for each call:
void print(int); // takes an integer argument
void print(double); // takes a floating-point argument
void print(string); // takes a string argument
void user()
{
print(42); // calls print(int)
print(9.65); // calls print(double)
print("D is for digital"); // calls print(string)
}
(1) Doesn't naming functions with the same name like this result in a (perhaps minor) performance hit?
(2) How exactly does the compiler "select" the most appropriate function, given the input? What is going on behind the scenes here?
Function overloading (at least normally) has no effect on execution speed. Consider if you wrote these functions as:
void print_int(int); // takes an integer argument
void print_double(double); // takes a floating-point argument
void print_string(string); // takes a string argument
...and then printed things out by choosing one of them based on what you wanted to print. That's pretty much what the compiler does: it takes the number and type of parameters, and encodes them into a "mangled" name. When you make a function call, the compiler (at compile time) looks through the available functions, chooses one, and creates a call to that function. The code to call the function is identical to code for calling a function that hasn't been overloaded.
Selecting the best function is a non-trivial exercise, to put it mildly. It takes place in a few phases. The first is to find a scope at which there's something defined with the name you've used. The second is to look through everything at that scope with that name to create a list of overloads.
The next step is to eliminate overloads that couldn't possibly work at all--e.g., overloads that simply can't accept the number of arguments you've passed. If that leaves only one function, overload resolution is done. If there's more than one, we get to the final (and trickiest) part of overload resolution.
The compiler starts with a list of possible implicit conversions for each type, and a ranking for each. The "best" is identity conversion (i.e., no conversion at all, such as if you're passing an int and the function expects an int). Slightly worse (but still fairly good) is something like adding a const. Eventually, you get to things like truncating a double to an int.
The compiler then goes through arguments one at a time, and looks at the conversion necessary to get from that argument to the type for the formal parameter. To qualify as the "best" overload and be chosen for use, at least one argument must have a "better" conversion than the conversion for any other overload, and none of the arguments can have a conversion that's worse than the overload that would be needed for any other overload.
If there is no such thing (e.g., you have only two viable functions, and each has one parameter that has a better conversion, and one argument with a worse conversion) the call is ambiguous, so the code can't compile.
(1) There is no performance hit at runtime, because the compiler figures out which function to call and calls it, just the same as any other function.
(2) Name mangling.
In your example, when you write
void print(int); // takes an integer argument
void print(double); // takes a floating-point argument
void print(string); // takes a string argument
the compiler gives them different names based on their parameter types, perhaps:
void print_i(int); // takes an integer argument
void print_d(double); // takes a floating-point argument
void print_str(string); // takes a string argument
Then when you call print(42), it says "Oh, it's called with an int, so let's actually call print_i(42)."
(1) In an ideal case, there is no extra cost. However, if the functions are exported by a shared library, there might be a larger run-time cost due to symbol resolution when the function is called for the first time. This is fully dependent on the dynamic linker implementation.
For example, if the dynamic linker in some exotic environment uses a simple hash table with a bad hash function (e.g. considers only the prefix of a symbol), hash collisions might make each lookup take O(n) time.
I need to write a function which takes a variable number of arguements, its essentially a wrapper around a snprintf like function. I understand how to do this in general as shown in Passing variable number of arguments around.
How ever it appears that, atleast in C, we are required to pass one named parameter to the function before the variable arguments start( Why is void f(...) not allowed in C? ).
However the answers to the same questions say this is easily possible in C++. I was wondering how to achieve this, especially since the method for handling vararg functions seems to be the same as C(va_start, etc). Or are they referring to variadic templates?
So basically is it possible to write a variadic function with no named arguements, as shown below, and if so, how?
void f(...){
...
}
p.s. I would like to do this with c++03 if possible.
While C++ language allows writing functions whose parameter list consist only of ..., the language provides no means for accessing the arguments in functions declared with (...) parameter list.
Basically such functions in C++ exist for their behavior in overload resolution (... parameters match any parameter type). The body of such function will not have access to the arguments. If you see no uses for such functions, just don't use them.
Such functions are often used in non-executed context in some well-known template meta-programming techniques, in which case they don't even have to be defined - a mere declaration is sufficient.
I'm experimenting with variable arguments in C++, using va_args. The idea is useful, and is indeed something I've used a lot in C# via the params functionality. One thing that frustrates me is the following excerpt regarding va_args, above:
Notice also that va_arg does not determine either whether the retrieved argument is the last argument passed to the function (or even if it is an element past the end of that list).
I find it hard to believe that there is no way to programmatically determine the number of variable arguments passed to the function from within that function itself. I would like to perform something like the following:
void fcn(int arg1 ...)
{
va_list argList;
va_start(argList, arg1);
int numRemainingParams = //function that returns number of remaining parameters
for (int i=0; i<numRemainingParams; ++i)
{
//do stuff with params
}
va_end(argList);
}
To reiterate, the documentation above suggests that va_arg doesn't determine whether the retrieved arg is the last in the list. But I feel this information must be accessible in some manner.
Is there a standard way of achieving this?
I find it hard to believe that there is no way to programmatically determine the number of variable arguments passed to the function from within that function itself.
Nonetheless, it is true. C/C++ do not put markers on the end of the argument list, so the called function really does not know how many arguments it is receiving. If you need to mark the end of the arguments, you must do so yourself by putting some kind of marker at the end of the list.
The called function also has no idea of the types or sizes of the arguments provided. That's why printf and friends force you to specify the precise datatype of the value to interpolate into the format string, and also why you can crash a program by calling printf with a bad format string.
Note that parameter passing is specified by the ABI for a particular platform, not by the C++/C standards. However, the ABI must allow the C++/C standards to be implementable. For example, an ABI might want to pass parameters in registers for efficiency, but it might not be possible to implement va_args easily in that case. So it's possible that arguments are also shadowed on the stack. In almost no case is the stack marked to show the end of the argument list, though, since the C++/C standards don't require this information to be made available, and it would therefore be unnecessary overhead.
The way variable arguments work in C and C++ is relatively simple: the arguments are just pushed on the stack and it is the callee's responsibility to somewhat figure out what arguments there are. There is nothing in the standard which provides a way to determine the number of arguments. As a result, the number of arguments are determined by some context information, e.g., the number of elements referenced in a format string.
Individual compilers may know how many elements there are but there is no standard interface to obtain this value.
What you could do instead, however, is to use variadic templates: you can determine very detailed information on the arguments being passed to the function. The interface looks different and it may be necessary to channel the arguments into some sort of data structure but on the upside it would also work with types you cannot pass using variable arguments.
No, there isn't. That's why variable arguments are not safe. They're a part of C, which lacks the expressiveness to achieve type safety for "convenient" variadic functions. You have to live with the fact that C contains constructions whose very correctness depends on values and not just on types. That's why it is an "unsafe language".
Don't use variable arguments in C++. It is a much stronger language that allows you to write equally convenient code that is safe.
No, there's no such way. If you have such a need, it's probably best to pack those function parameters in a std::vector or a similar collection which can be iterated.
The variable argument list is a very old concept inherited from the C history of C++. It dates back to the time where C programmers usually had the generated assembler code in mind.
At that time the compiler did not check at all if the data you passed to a function when calling it matched the data types the function expected to receive. It was the programmer's responsibility to do that right. If, for example, the caller called the function with a char and the function expected an int the program crashed, although the compiler didn't complain.
Today's type checking prevents these errors, but with a variable argument list you go back to those old concepts including all risks. So, don't use it if you can avoid it somehow.
The fact that this concept is several decades old is probably the reason that it feels wrong compared to modern concepts of safe code.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
C++ Why put void in params?
What's the difference between these two declarations and which is used more commonly?
void function1();
and
void function2( void );
There is no difference in C++, where it is well defined that it represents 0 parameters.
However it does make one in C. A function with (void) means with no parameter, whereas () means with any number of parameters.
From http://publib.boulder.ibm.com/infocenter/comphelp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8a.doc%2Flanguage%2Fref%2Fparam_decl.htm
An empty argument list in a function definition indicates that a function
that takes no arguments. An empty argument list in a function declaration
indicates that a function may take any number or type of arguments. Thus,
int f()
{
...
}
indicates that function f takes no arguments. However,
int f();
simply indicates that the number and type of parameters is not known.
To explicitly indicate that a function does not take any arguments, you should
define the function with the keyword void.
There is no difference in C++.
The second declaration just explicitly says that function takes no parameter.
Second is more commonly used in C, First is the one that is more common in C++.
There is a difference in case of C because:
With (void), you're specifying that the function has no parameters, while with () you are specifying that the parameters are unspecified(unknown number of arguments).
However, if it was not a function declaration but a function definition, then even in C it is same as (void).
There is no difference. I'd say the first one is more common, clear and concise.
In C++, there is no difference, and the second form is only retained for C compatibility. The first form is preferred in C++.
In C, they mean different things.
The first form specifies a function which takes an unknown number of arguments, and the second is a function taking zero arguments.
Some very old (non-standard) C compiler might complain about the first one, so the second one should be more portable.
Apart from that, there is no difference.
The first one is used more commonly in user code, quite simply because it's shorter.
actually there is no difference .if you have not any parameters to pass to the method user void or empty parentheses .notice that it just fro passed parameters.if your method has not any returned value you have to use void keyword.the first one is more common in C#
I wanted to have function which will accept as
foo(...)
{
//......
}
usage of this would be
foo(1,2,3);
foo(1)
foo(1,2,3,4,5,5,6);
va_list can be used but again for that I have to pass foo(int count, ...), as this at run time i dont know how many argument i have.
any pointer would be appreciated
Thanks
You need to provide the function some way to determine how many arguments it's called with: either a count (or something from which a count can be determined, such as printf's format argument), or a terminator (none of the arguments will be allowed to be equal to the terminator, except the last one that must be exactly equal to the terminator). The function can't just know "by magic" when its variadic list of arguments is finished.
Variadic functions in C and C++ are not type-safe. So you cannot do what you want without some mechanism for marking the end of the argument list. You also need to have at least one "fixed" argument so that the macros can know where the start of your argument list is in memory.
This is the reason why passing the "count" as the first argument is useful: it solves both of those problems in one hit.
Note that it works out OK for things like printf because the format string is a fixed parameter, and the "count" of variadic argument is implicit in the format string.
It's not possible to build an argument list at runtime in C, so it is absolutely certain that you know how many arguments each call to f() is using at compile-time.