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?

5
  • See below, but FAMs usually compile correctly in C++. Commented Aug 7, 2015 at 16:06
  • Note: Since get_buf() make_struct() only use a pointer to struct x, why is struct x even defined in blah.h? Commented Aug 7, 2015 at 16:07
  • I'm rolling this question back to the prior version. If you have a new question, you are welcome to ask it, but your last edit appears to be an attempt to invalidate all the answers you received. Commented Aug 7, 2015 at 16:08
  • @DrewDormann I made this clearly extern "C" and asked the linkage question independantly Commented Aug 7, 2015 at 16:40
  • 1
    If this was not language-lawyer, I'd point out that #ifdef guarding char buf[]; out of existence makes the code work. Commented Aug 8, 2015 at 4:54

4 Answers 4

19

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

Sign up to request clarification or add additional context in comments.

2 Comments

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.
@KennyOstrom: Yes, that's what I was suggesting (though not as clearly as you did). I'll update my answer.
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.

2 Comments

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

Comments

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

2 Comments

Missed the point; the question is whether extern "C" makes valid C / illegal C++ into a sort of pseudo legal C++.
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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.