Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does extern C with C++ avoid undefined behavior that is legal in C but not C++?

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?

like image 264
Glenn Teitelbaum Avatar asked Aug 07 '15 15:08

Glenn Teitelbaum


People also ask

Can you use extern C in C?

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.

Why does C allow undefined behavior?

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.

What is the point of extern C?

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.

What type of behavior C is undefined?

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.


2 Answers

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.)

like image 162
Keith Thompson Avatar answered Oct 11 '22 04:10

Keith Thompson


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.

like image 27
Quentin Avatar answered Oct 11 '22 03:10

Quentin