If you use extern C
it with C++ files, does that allow defined C behavior that is undefined in C++?
blah.h
extern "C"
{
struct x {
int blah;
char buf[];
};
char * get_buf(struct x * base);
struct x * make_struct(int blah, int size);
}
some_random.cpp
#include "blah.h"
...
x * data=make_struct(7, 12);
std::strcpy(get_buf(data), "hello");
Is using the defined behavior in C's flexible array member, defined behavior when used this way?
By declaring a function with extern "C" , it changes the linkage requirements so that the C++ compiler does not add the extra mangling information to the symbol. This pattern relies on the presence of the __cplusplus definition when using the C++ compiler. If you are using the C compiler, extern "C" is not used.
It exists because of the syntax rules of C where a variable can be declared without init value. Some compilers assign 0 to such variables and some just assign a mem pointer to the variable and leave just like that. if program does not initialize these variables it leads to undefined behavior.
extern "C" specifies that the function is defined elsewhere and uses the C-language calling convention. The extern "C" modifier may also be applied to multiple function declarations in a block. In a template declaration, extern specifies that the template has already been instantiated elsewhere.
According to the C standards, signed integer overflow is undefined behaviour too. A few compilers may trap the overflow condition when compiled with some trap handling options, while a few compilers simply ignore the overflow conditions (assuming that the overflow will never happen) and generate the code accordingly.
Flexible array members are a standard feature of C, starting with the 1999 standard. They do not exist in C++.
Your code is not valid C++. Wrapping it in extern "C"
doesn't change that. A conforming C++ compiler must at least warn about it, and arguably should reject it.
It happens that g++ implements C-style flexible array members as an extension to C++. That's perfectly legitimate (compilers are allowed to implement extensions), but its use is not portable. Its behavior, like that of any language extension, is defined by the compiler, not by the language.
If you compile it with g++ -pedantic
, you'll get a warning:
c.cpp:5:21: warning: ISO C++ forbids zero-size array ‘buf’ [-Wpedantic]
char buf[];
^
If you want to use C-style flexible array members in a C++ program without relying on a compiler-specific extension, you can compile your C code as C and link it into your C++ program. You can't make the type with the flexible array member visible to your C++ code, but you can use it internally in the C code, and perhaps provide access to it in your C++ code via an opaque pointer. See the C++ FAQ for information about mixing C and C++ within the same program. (Or you can just use the g++ extension, at the cost of not being able to compile your code with other compilers.)
(I'm assuming that you're using g++. Some other compilers probably implement similar extensions.)
No.
extern "C"
is only a linkage specification, so that enclosed symbols can be linked to from C. It does not switch your compiler to "C mode" for a section of code.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With