将C与C++链接是否可以避免在C中合法但未在C++中合法的未定义行为?

Gle*_*aum 20 c c++ language-lawyer

如果你有一个C文件,用C编译器编译并且已经为C而不是C++定义了行为,你可以将它与C++文件链接而不是没有未定义的行为吗?

在blah.c中(编译为C的文件)

struct x {
    int blah;
    char buf[];
};

extern char * get_buf(struct x * base);
extern struct x * make_struct(int blah, int size);
Run Code Online (Sandbox Code Playgroud)

blah_if.h

extern "C"
{
    struct x;

    char * get_buf(struct x * base);
    struct x * make_struct(int blah, int size);
}
Run Code Online (Sandbox Code Playgroud)

some_random.cpp(用C++编译器编译)

#include "blah_if.h"

...

x * data=make_struct(7, 12);
std::strcpy(get_buf(data), "hello");
Run Code Online (Sandbox Code Playgroud)

在使用C编译器编译的文件中使用C的灵活数组成员中定义的行为,当被编译为C++并与C编译器中的对象链接时使用的定义行为?

请注意,因为使用了C编译器并且它struct x是不透明的,所以这与以下内容不同:

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

Ray*_*hen 19

行为是实现定义的.

[dcl.link]从C++到其他语言定义的对象以及用其他语言在C++中定义的对象的链接是实现定义的和语言相关的.

它继续:

只有在两种语言实现的对象布局策略足够相似的情况下才能实现这种联系.

标准中的那句话确实应该是一个注释,因为它没有指明什么算得上"足够相似".


Lig*_*ica 12

正如Raymond已经说过的,这是在正式的语言层面上实现定义的.

但重要的是要记住编译后的代码什么.它不再是C++代码,也不是C代码.关于这些语言中的代码行为的规则适用于用这些语言编写的代码.在解析和翻译过程中会考虑它们.但是,一旦您的代码被转换为汇编,机器代码或其他任何您翻译成的代码,这些规则就不再适用.

因此,询问编译的C代码是否具有UB实际上毫无意义.如果你有一个定义良好的C程序,并编译它,就是这样.你不能讨论编译的程序是否定义良好.这是一个毫无意义的区别,除非您以某种方式设法生成一个程序,该程序根据您的程序集或机器语言方言的规范而被指定为UB.

所有这一切的结果是你的问题的前提是不健全的.链接到C程序的编译结果时,不能"避免未定义的行为",因为那里不存在"未定义行为"的概念.但是,只要原始源代码在翻译时定义得很好,你就可以了.

  • 这描述了一种编译模型,但不是唯一的模型.另一个模型是链接时代码生成 - 在此模型下,源代码被编译为中间语言,并且在链接时生成实际的汇编代码.那个中间语言可能有UB. (8认同)
  • @LightnessRacesinOrbit标准无法解决代码生成的问题.这是一个实现细节.[gcc](http://gcc.gnu.org/wiki/LinkTimeOptimization)和[Visual Studio](https://msdn.microsoft.com/en-us/library/xbf3tbeh(VS.80).aspx)支持它.它有时会被称为"整个程序优化". (8认同)