带C ++的extern C是否避免了在C中合法而不是C ++的未定义行为?

如果将extern C it与C ++文件一起使用,是否允许在C ++中未定义的已定义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"); 

在C的灵活数组成员中使用定义的行为,在使用这种方式时定义了行为吗?

灵活的arrays成员是C的标准function,从1999年标准开始。 它们不存在于C ++中。

您的代码无效C ++。 将它包装在extern "C"并不会改变它。 一个符合标准的C ++编译器必须至少警告它,并且可以说应该拒绝它。

碰巧g ++实现了C风格的灵活数组成员作为C ++的扩展。 这是完全合法的(允许编译器实现扩展),但它的使用不可移植。 它的行为与任何语言扩展的行为一样,由编译器定义,而不是由语言定义。

如果用g++ -pedantic编译它,你会收到警告:

 c.cpp:5:21: warning: ISO C++ forbids zero-size array 'buf' [-Wpedantic] char buf[]; ^ 

如果要在C ++程序中使用C风格的灵活数组成员而不依赖于特定于编译器的扩展,则可以将C代码编译为C并将其链接到C ++程序中。 您不能使用C ++代码可以看到灵活数组成员的类型,但您可以在C代码内部使用它,并且可能通过不透明指针在C ++代码中提供对它的访问。 有关在同一程序中混合使用C和C ++的信息,请参阅C ++ FAQ 。 (或者您可以使用g ++扩展,但代价是无法使用其他编译器编译代码。)

(我假设您正在使用g ++。其他一些编译器可能实现类似的扩展。)

没有。

extern "C"只是一个链接规范,因此封闭的符号可以从C链接。它不会将编译器切换到“C模式”代码段。

extern "C"声明仅影响外部函数的链接,因此不执行名称修改。 这并不意味着将使用C语言的规则而不是C ++编译函数。 换句话说,包括some_random.cpp的代码将不会定义其行为。

它只是ascii,直到编译器运行。 因此预处理器会将文件粘贴在一起,然后编译器会将结果视为您指定的任何语言。

它不是C flexible数组成员,它是一个文本文件。 未定义的行为仍然存在。