14

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?

Glenn Teitelbaum
  • 10,108
  • 3
  • 36
  • 80

4 Answers4

18

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

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
  • 4
    You may need to hide struct x's actual definition from the c++ header, and treat it as an opaque pointer except when you access it through the defined C functions. – Kenny Ostrom Aug 07 '15 at 16:02
  • @KennyOstrom: Yes, that's what I was suggesting (though not as clearly as you did). I'll update my answer. – Keith Thompson Aug 07 '15 at 18:14
11

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.

Quentin
  • 62,093
  • 7
  • 131
  • 191
  • @GlennTeitelbaum It doesn't matter : the problem is that flexible array members don't *exist* in C++. Even if only a C compiler got to see it used (it's not the case, you try to `std::copy` to it), the C++ compiler would choke on its declaration alone. – Quentin Aug 07 '15 at 16:02
  • 2
    True, flexible array members don't exist in standard C++, but they do exist in the g++ dialect of C++, as a compiler-specific extension. – Keith Thompson Aug 07 '15 at 18:16
10

An extern "C" declaration only affects linkage of external functions, so that name mangling is not performed. It doesn't mean that the functions will be compiled using the rules of the C language instead of C++. In other words, including the code in some_random.cpp will not make its behavior defined.

user4815162342
  • 141,790
  • 18
  • 296
  • 355
-5

It's just ascii until such time as the compiler runs. So the preprocessor will paste the files together, then the compiler will treat the result as whatever language you specified.

It isn't a C flexible array member, it's a text file. Undefined behaviour remains.

Jon Chesterfield
  • 2,251
  • 1
  • 20
  • 30
  • 5
    Missed the point; the question is whether `extern "C"` makes valid C / illegal C++ into a sort of pseudo legal C++. – Lightness Races in Orbit Aug 07 '15 at 16:57
  • It didn't occur to me that extern C could be expected to achieve so much, while determining what language a text file is processed as seems to throw people. Thank you for your comment. – Jon Chesterfield Aug 07 '15 at 17:05