I know when i want to link C code as C code in C++ should i use extern "C". But with the following code :
/* file.h */
some (void)
{
return 10;
}
extern "C"
{
#include "file.h"
}
#include <iostream>
int main (void)
{
std::cout << some() << std::endl;
}
I get this compile time error:
C4430: missing type specifier - int assumed. Note: C++ does not support defualt-int.
How i can deal with this ?
I use MSVC2017 on MS-Windows10.
EDIT: I know that most declare the function with a explicit return type, But i what to use USBPcap and USBPcap declare some function like that. How i can use it in my own C++ program ?
All functions should specify a return type. You aren't specifying one for some.
In older versions of C, if you omit the return type of a function it defaults to int. C++ however doesn't support that.
You should always specify a function's return type:
int some(void)
{
return 10;
}
extern "C" only changes the linkage of declarations. In particular, it disables C++ name mangling that is otherwise needed for some C++ features such as overloading.
extern "C" does not make the enclosed part of the program to be compiled as C. As such, the declarations must still be well-formed C++. some (void) is not a well-formed declaration in C++, which explains the error.
How i can deal with this ?
Declare the return type explicitly.
USBPcap declare some function like that. How i can use it in my own C++ program ?
Then you cannot use that header. You can write a C++ compatible header yourself. Or, you can use a C++ compiler that supports impilict int as an extension.
P. S. Implicit int is not well-formed in C language either since C99.
Do not put any code to the .h files except static inline functions
Secondly declare the functions correctly - not the lazy way. What is some(void)? If the C++ compiler knew the return type of the function ....
extern "C"
{
int some (void)
{
return 10;
}
}
#include <iostream>
int main (void)
{
std::cout << some() << std::endl;
}
https://godbolt.org/z/_AJgFX
The compiler have say to you exactly what is the problem. The function that you are trying to call from std::cout need to have a returned type explicitly defined. In C the compiler automatically set the return type of an undefined-type function to int and you can compile a code that contain untyped function with nothing more of a warning from the compiler , but not do it, it is extremely wrong way to write code. In C++, just like the compiler told you, you can't, so it is an error. The definitions in C and C++ must have a type, if you want a function that not return anything, you need define it void.
However, in the last versions of the c++ standards you can use the auto keyword to auto detect the type of a declaration at compile time, so if you want that the compiler auto detect the type of something, use it, but use it with sparingly.
So, finally, if you want write C or C++ code, please, add a type to your definitions, this isn't python or javascript...
Related
I tried to google and quick search on latest draft for "C lang" and "C18" on openstd org.
Will C++ standard support the latest standards of C?
C++ is a general purpose programming language based on the C programming language as described in ISO/IEC 9899:2018 Programming languages — C (hereinafter referred to as the C standard).
C++ provides many facilities beyond those provided by C, including additional data types, classes, templates, exceptions, namespaces, operator overloading, function name overloading, references, free store management operators, and additional library facilities.
http://eel.is/c++draft/intro.scope
C18 (previously known as C17) is the informal name for ISO/IEC 9899:2018, the most recent standard for the C programming language, published in June 2018. It replaced C11 (standard ISO/IEC 9899:2011).
https://en.m.wikipedia.org/wiki/C18_(C_standard_revision)
C++ (of any version) does not include C (of any version) wholesale. It merely references parts of the C specification as needed. For example, C++ includes (most) of the C standard library, and it does so by referencing the appropriate parts of the C standard instead of copying from it.
When C++20 references a version of the C specification, it references C18.
I believe the reasoning behind your question is that, when you use extern "C" in C++, it somehow invokes a separate C compiler of a specific version.
It doesn't. What extern "C" does is tell the C++ compiler to use C linkage for the functions so that other code using C linkage can properly link to these functions. It doesn't affect how the source code is compiled, apart from throwing compiler errors if you try to overload non-member functions inside the extern block.
The C++ compiler will not complain a bit if you write something like this:
extern "C" {
// this is still a C++ compiler, works as usual
class CPP
{
public:
// these are inside a class and can be overloaded,
// and they will be mangled as usual
static int foo(int i) { return i; };
static int foo(int i, int j) { return i + j; }
};
// these will not be mangled due to 'extern "C"'
int foo(int i) { return CPP::foo(i); }
int bar(int i, int j) { return CPP::foo(i, j); }
}
At the same time this simple C code will fail in any C++ compiler:
int * x = malloc(1);
As will this code from C11, since _Atomic is not a valid qualifier in the C++ standard:
#include <stdatomic.h>
_Atomic int x;
#include <iostream>
#include <cmath>
/* Intentionally incorrect abs() which seems to override std::abs() */
int abs(int a) {
return a > 0? -a : a;
}
int main() {
int a = abs(-5);
int b = std::abs(-5);
std::cout<< a << std::endl << b << std::endl;
return 0;
}
I expected that the output will be -5and 5, but the output is the -5 and -5.
I wonder why this case will happen?
Does it have anything to do with the use of std or what?
The language specification allows implementations to implement <cmath> by declaring (and defining) the standard functions in global namespace and then bringing them into namespace std by means of using-declarations. It is unspecified whether this approach is used
20.5.1.2 Headers
4 [...] In the C++ standard library, however, the declarations (except for names which are defined as macros in C) are within namespace scope (6.3.6) of the namespace std. It is unspecified whether these names (including any overloads
added in Clauses 21 through 33 and Annex D) are first declared within the global namespace scope and are then injected into namespace std by explicit using-declarations (10.3.3).
Apparently, you are dealing with one of implementations that decided to follow this approach (e.g. GCC). I.e. your implementation provides ::abs, while std::abs simply "refers" to ::abs.
One question that remains in this case is why in addition to the standard ::abs you were able to declare your own ::abs, i.e. why there's no multiple definition error. This might be caused by another feature provided by some implementations (e.g. GCC): they declare standard functions as so called weak symbols, thus allowing you to "replace" them with your own definitions.
These two factors together create the effect you observe: weak-symbol replacement of ::abs also results in replacement of std::abs. How well this agrees with the language standard is a different story... In any case, don't rely on this behavior - it is not guaranteed by the language.
In GCC this behavior can be reproduced by the following minimalistic example. One source file
#include <iostream>
void foo() __attribute__((weak));
void foo() { std::cout << "Hello!" << std::endl; }
Another source file
#include <iostream>
void foo();
namespace N { using ::foo; }
void foo() { std::cout << "Goodbye!" << std::endl; }
int main()
{
foo();
N::foo();
}
In this case you will also observe that the new definition of ::foo ("Goodbye!") in the second source file also affects the behavior of N::foo. Both calls will output "Goodbye!". And if you remove the definition of ::foo from the second source file, both calls will dispatch to the "original" definition of ::foo and output "Hello!".
The permission given by the above 20.5.1.2/4 is there to simplify implementation of <cmath>. Implementations are allowed to simply include C-style <math.h>, then redeclare the functions in std and add some C++-specific additions and tweaks. If the above explanation properly describes the inner mechanics of the issue, then a major part of it depends on replaceability of weak symbols for C-style versions of the functions.
Note that if we simply globally replace int with double in the above program, the code (under GCC) will behave "as expected" - it will output -5 5. This happens because C standard library does not have abs(double) function. By declaring our own abs(double), we do not replace anything.
But if after switching from int with double we also switch from abs to fabs, the original weird behavior will reappear in its full glory (output -5 -5).
This is consistent with the above explanation.
Your code causes undefined behaviour.
C++17 [extern.names]/4:
Each function signature from the C standard library declared with external linkage is reserved to the implementation for use as a function signature with both extern "C" and extern "C++" linkage, or as a name of namespace scope in the global namespace.
So you cannot make a function with the same prototype as the Standard C library function int abs(int);. Regardless of which headers you actually include or whether those headers also put C library names into the global namespace.
However, it would be allowed to overload abs if you provide different parameter types.
I know that meaning of auto keyword has been changed completely from C++11. But Recently I wrote a following simple program that compiles & runs fine when compiling with =std=c++98 option.
#include <iostream>
void fun(auto int a)
{
a=3;
std::cout<<a<<'\n';
}
int main()
{
fun(3);
}
Orwell Dev C++ IDE gives me warning like following:
[Warning] 'auto' changes meaning in C++11; please remove it [-Wc++0x-compat]
So, is it fine to use auto for function parameters or should I never use auto like this as in above program to maintain compatibility with C++11?
Until C++ 11 the auto keyword was a "storage class specifier" whereas with C++ 11 it becomes a type-induction specifier.
To answer your question: depending on the C++ standard you use to compile your code, adjust the use of the auto keyword accordingly. It's not portable across the pre/post C++ 11 boundary of the C++ standard.
So, is it fine to use auto for function parameters or should I never use auto like this as in above program to maintain compatibility with C++11?
That depends on what you mean by "fine":
If you mean "will it compile?" then YES.
If you mean "is it a good practice", the answer is that it is not a practice at all; It was possible to do so and the code was perfectly valid (before C++11) but that time is passed, and I do not know of anyone who did this (not even for tricky interview questions).
In conclusion, don't do it.
auto prior to C++11 was a storage class specifier, like register or static or extern.
It, however, was the default storage class specifier. Valid C++03 code with it removed would have the same meaning, which is why C++11 felt comfortable stealing the keyword.
In short:
void fun1(auto int a) {
std::cout<<a<<'\n';
}
void fun2(int a) {
std::cout<<a<<'\n';
}
have the same meaning in C++03. In C++11, fun1 is ill-formed.
Simply remove it from all of your pre-C++11 codebases. If the code was valid C++03, it will continue to have the same meaning.
There is a (very small) problem that some compilers might implement the K&R era C "by default, a type is int". Ie, they might consider auto x; to mean auto int x;. This was not valid C++03, however. Compiling with sufficiently strict flags in C++03 mode should generate errors around that (ab)use of auto.
As an aside, C++11 also introduces a new storage class specifier, thread_local. It steals auto for the use of auto-typed variables, and auto is no longer a storage class specifier.
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.