I have an exported function in a dll(written in vc++) which has got variable no. of arguments. Now I want to overload this function without variable no. of arguments. Is there anything wrong with this concept? The reason I am concerned is because I have read that vc++ uses __cdecl calling convention for c and c++.
Sample signatures are given below.
void f(int i, char *fmt, ...);
void f(int i, string str);
It depends from where are you planning to call these functions.
They should be converted to names like f__FiPc?? and f__Fi6string.
C++ compiler will decode them and C compiler will miss the function f if you haven't declared extern "c". However it depends on the implementation of your compiler.
Related
Consider these two function definitions:
void foo() { }
void foo(void) { }
Is there any difference between these two? If not, why is the void argument there? Aesthetic reasons?
In C:
void foo() means "a function foo taking an unspecified number of arguments of unspecified type"
void foo(void) means "a function foo taking no arguments"
In C++:
void foo() means "a function foo taking no arguments"
void foo(void) means "a function foo taking no arguments"
By writing foo(void), therefore, we achieve the same interpretation across both languages and make our headers multilingual (though we usually need to do some more things to the headers to make them truly cross-language; namely, wrap them in an extern "C" if we're compiling C++).
I realize your question pertains to C++, but when it comes to C the answer can be found in K&R, pages 72-73:
Furthermore, if a function declaration does not include arguments, as
in
double atof();
that too is taken to mean that nothing is to be assumed about the
arguments of atof; all parameter checking is turned off. This special
meaning of the empty argument list is intended to permit older C
programs to compile with new compilers. But it's a bad idea to use it
with new programs. If the function takes arguments, declare them; if
it takes no arguments, use void.
C++11 N3337 standard draft
There is no difference.
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3337.pdf
Annex C "Compatibility" C.1.7 Clause 8: declarators says:
8.3.5 Change: In C ++ , a function declared with an empty parameter list takes no arguments. In C, an empty
parameter list means that the number and type of the function arguments are unknown.
Example:
int f();
// means int f(void) in C ++
// int f( unknown ) in C
Rationale: This is to avoid erroneous function calls (i.e., function calls with the wrong number or type of
arguments).
Effect on original feature: Change to semantics of well-defined feature. This feature was marked as “obsolescent” in C.
8.5.3 functions says:
4. The parameter-declaration-clause determines the arguments that can be specified, and their processing, when
the function is called. [...] If the parameter-declaration-clause is empty, the function
takes no arguments. The parameter list (void) is equivalent to the empty parameter list.
C99
As mentioned by C++11, int f() specifies nothing about the arguments, and is obsolescent.
It can either lead to working code or UB.
I have interpreted the C99 standard in detail at: https://stackoverflow.com/a/36292431/895245
In C, you use a void in an empty function reference so that the compiler has a prototype, and that prototype has "no arguments". In C++, you don't have to tell the compiler that you have a prototype because you can't leave out the prototype.
I'm supposed to put my implementations in one file and my prototypes in a header file. But the way I understand it, a header file full of prototypes would not be very useful. What are these things? Is one of them identical to a definition or a declaration?
A function prototype is a function declaration that declares the types of its arguments. This distinction is historical. In C, it is possible to declare a function without a prototype, but in C++ all function declarations are prototypes (so there is no difference in C++).
// In C, this is a declaration but NOT a prototype.
// In C, this function takes an unknown number of parameters.
// In C++, this is a prototype, and the function has no arguments.
void f();
// In C, this is a prototype for a function with no arguments.
// In C++, it is the same thing.
void f(void);
In C++, you can't call functions unless you have a declaration/prototype for the function. That is the use of header files.
(In C, you can call functions without a declaration, but this is considered a bad idea, and you only see it in really old code.)
A function prototype is a declaration of a function: its name, parameters and return type. Unlike a full definition, the prototype terminates in a semi-colon.
int myfunc(double param) ;
The actual names of the parameter values (param in above example) can be left out of the prototype. This gives the flexibility of renaming variables at will.
Prototypes are used in header files so that external functions from other files can be called and the compiler can check the parameters during compilation.
A function prototype can be used to forward declare a function. A forward declaration is when a function or class is declared in advance of where it is implemented.
With normal functions, one can write
extern "C" int Frotz(int); // in a header
int Frotz(int x) { return x; }
With function pointers, however, this appears to have been implemented inconsistently between compilers.
extern "C" int Klutz(int (*)(int), int);
int Klutz(int (*fptr)(int), int x) { return (*fptr)(x); }
In the declaration, the argument is also extern "C". In the definition, most compilers appear to match these functions and make Klutz an extern "C" function. The Sun and Cray compilers, however, interpret these functions as being different, producing an overloaded int Klutz(int (*fptr)(int), int x), which later generates a link-time error.
Although Section 7.5.5 of C++98 and C++11 guarantees the interpretation of Frotz, I cannot tell if the standard is ambiguous about whether extern "C" matching should occur before or after checking for overloading.
Should Klutz above generate a mangled (C++) symbol or an extern "C" symbol?
EDIT 1
I could use a typedef to disambiguate the function pointer to have C or C++ ABI, but I'm interested in whether the code here (a) defines Klutz to have C++ linkage, (b) defines it to have C linkage, or (c) is ambiguous according to the standard, so that compilers are free to choose how to interpret it.
EDIT 2
This appears to be a known issue, at least by those compilers with searchable bug trackers. In my tests, GCC, Clang, Intel, MSVC, IBM XL, PathScale, PGI, and Open64 all fail to distinguish function types that are identical except for language linkage, as explicitly required by the standard (see section 7.5.1, quoted in the accepted answer). Fixing this would break a lot of existing code and require an ABI change. I'm not aware of any compiler that actually uses a different calling convention for C versus C++ language linkage.
GCC bug: "Finding reasons to ask for the removal of this feature from the next standard is kind of relevant ;-)" ... "And we may even decide on an official WONTFIX."
Clang bug: "I'm terrified of actually enforcing this rule, because doing it properly means making language linkage part of the canonical type, which is going to break a ton of code."
The C ABI and the C++ ABI are not guaranteed to be the same. So, an extern "C" function pointer is a different type from a C++ function pointer. You need something like this:
extern "C" {
typedef int (*KlutzFuncType)(int);
int Klutz (KlutzFuncType, int);
}
int Klutz (KlutzFuncType fptr, int x) { return (*fptr)(x); }
There is some discussion of this issue here.
I only have a copy of the draft. From 7.5p1:
Two function types with different language linkages are distinct types even if they are otherwise identical.
My reading of this is that the first parameter of your first Klutz has a different type than the first parameter of your second Klutz, and so your second Klutz should have C++ linkage.
There are C++ implementations that do not take language linkage into account for function types, despite what the standard says. In the following code snippet, KlutzCxxFuncType refers to a function with C++ linkage, while KlutzCFuncType refers to a function with C linkage.
typedef int (*KlutzCxxFuncType)(int);
extern "C" {
typedef int (*KlutzCFuncType)(int);
int Klutz (KlutzCFuncType, int);
}
int Klutz (KlutzCxxFuncType fptr, int x) { return (*fptr)(x); }
int Klutz (KlutzCFuncType fptr, int x) { return (*fptr)(x); }
A compiler that does not distinguish function types based on language linkage will generate a redefinition error on this code. For example, g++ 4.7.2 will emit:
prog.cpp: In function ‘int Klutz(KlutzCFuncType, int)’:
prog.cpp:9:5: error: redefinition of ‘int Klutz(KlutzCFuncType, int)’
prog.cpp:8:5: error: ‘int Klutz(KlutzCxxFuncType, int)’ previously defined here
Suppose I have this function:
void func() {}
When I call func with some parameters (e.g. func(132)), the C++ compiler yields an error, while the C compiler doesn't.
What is the difference between the two compilers in this case? And what advantages/disadvantages the C++ has by arising this error?
There are no advantages or disadvantages. C supports this for compatibility with K&R C from the 1980s. You might like this feature if you are still using code you wrote in the 1980s. You might dislike this feature if you want better diagnostics from your compiler.
void func();
In C, this means that func takes unspecified parameters.
If you need to specify that the function takes no parameters, write it this way:
void func(void);
In C++ the two prototypes are the same. (In C, only the second one is a prototype.) If you compile with GCC/Clang's -Wstrict-prototypes option, you will get warnings for using void func(); in C, as you should.
This is only about function declarations. In both languages, the following function definitions are the same:
// These two are the SAME
void func() { }
void func(void) { }
// These two are DIFFERENT
void func();
void func(void);
In C++, that function has no arguments. In C, it means an indeterminate number of arguments.
This is a holdover from the very earliest days of C where every function returned an int and it was much more relaxed about arguments being passed.
Consider these two function definitions:
void foo() { }
void foo(void) { }
Is there any difference between these two? If not, why is the void argument there? Aesthetic reasons?
In C:
void foo() means "a function foo taking an unspecified number of arguments of unspecified type"
void foo(void) means "a function foo taking no arguments"
In C++:
void foo() means "a function foo taking no arguments"
void foo(void) means "a function foo taking no arguments"
By writing foo(void), therefore, we achieve the same interpretation across both languages and make our headers multilingual (though we usually need to do some more things to the headers to make them truly cross-language; namely, wrap them in an extern "C" if we're compiling C++).
I realize your question pertains to C++, but when it comes to C the answer can be found in K&R, pages 72-73:
Furthermore, if a function declaration does not include arguments, as
in
double atof();
that too is taken to mean that nothing is to be assumed about the
arguments of atof; all parameter checking is turned off. This special
meaning of the empty argument list is intended to permit older C
programs to compile with new compilers. But it's a bad idea to use it
with new programs. If the function takes arguments, declare them; if
it takes no arguments, use void.
C++11 N3337 standard draft
There is no difference.
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3337.pdf
Annex C "Compatibility" C.1.7 Clause 8: declarators says:
8.3.5 Change: In C ++ , a function declared with an empty parameter list takes no arguments. In C, an empty
parameter list means that the number and type of the function arguments are unknown.
Example:
int f();
// means int f(void) in C ++
// int f( unknown ) in C
Rationale: This is to avoid erroneous function calls (i.e., function calls with the wrong number or type of
arguments).
Effect on original feature: Change to semantics of well-defined feature. This feature was marked as “obsolescent” in C.
8.5.3 functions says:
4. The parameter-declaration-clause determines the arguments that can be specified, and their processing, when
the function is called. [...] If the parameter-declaration-clause is empty, the function
takes no arguments. The parameter list (void) is equivalent to the empty parameter list.
C99
As mentioned by C++11, int f() specifies nothing about the arguments, and is obsolescent.
It can either lead to working code or UB.
I have interpreted the C99 standard in detail at: https://stackoverflow.com/a/36292431/895245
In C, you use a void in an empty function reference so that the compiler has a prototype, and that prototype has "no arguments". In C++, you don't have to tell the compiler that you have a prototype because you can't leave out the prototype.