C++程序到底是如何编译的,真的是先将其翻译成 C 程序?

2017-09-11 20:44:05 +08:00
 douglas1997

在上 coursea 的 C++课程,颠覆了以前 C 编程中的看法。

#include <iostream>
using namespace std;
class A{
    int i;
    public:
        void Hello(){ cout << "hello" << endl; }
};
int main(){
    A * p = NULL;
    p->Hello();
    return 0;
}

这玩意的编译输出是 hello。这样真的好吗。。。

2456 次点击
所在节点    问与答
13 条回复
zts1993
2017-09-11 20:53:28 +08:00
这个有点颠覆我的认知: 这个不会 core 么??
jlsk
2017-09-11 21:04:35 +08:00
正常,你把 Hello()改成 cout <<i<< endl;就知道错了
03
2017-09-11 21:07:55 +08:00
对于标题:这都什么时候的事情了

https://stackoverflow.com/questions/2505328/calling-class-method-through-null-class-pointer 一样

这样很好啊,反正你的 Hello()不与具体对象相关,直接就解释为调用那个函数不就可以了,反正对一个无效指针调用是你的责任而不是 C++有义务检查
douglas1997
2017-09-11 21:14:17 +08:00
@jlsk 这个我知道,关键是这样去实现是不是不太好?(不太直觉)
douglas1997
2017-09-11 21:18:44 +08:00
@zts1993 不 core 不 core hhh
zmj1316
2017-09-11 21:28:11 +08:00
这个和 C 有什么关系...虽然传进去的 this 是个 null ,反正又没调用到,你的函数要是个虚函数应该就跪了
acros
2017-09-11 21:34:27 +08:00
为啥会有这种写法,是为了教学说明类的内存布局吧?
secondwtq
2017-09-11 21:36:32 +08:00
如果你对 C++ 足够熟悉,那么你可以以相对直接的方式把 C++ 程序翻译成等效的 C 程序。最早的 C++ 编译器就是这么干的。
之所以强调 相对直接,是因为在 Compiler 中,C 语言实际上相当于高级汇编,最近几年比较流行 codegen 编译到 LLVM IR,实际上更早的时候有不少是编译到 C 语言的,比如 GHC 最后一层的 IR 叫 C--,Gnome 的 Vala 也是这么干的
如果不计较这个编译过程的逻辑和复杂性,以及运行时系统的介入程度的话,JS 都可以编译到 C。对于 C++ 自己的体量和设计来说,翻译到 C 的过程(尤其是楼主所用的这个子集)是相对直接的。
详见 https://isocpp.org/wiki/faq/compiler-dependencies#convert-to-c

对于一个要与 C 争市场的语言来说,“这么实现”是完全没问题的。“不太好”的反而在于楼主的用法,一般 C++ 不提倡 hack,尤其是这种会 UB 的 hack。

建议楼主可以多看看出来的汇编,还有 Inside the C++ Object Model 这种书,了解了一个特性,可以多想一步这个是怎么实现的。

这里其实有一个坑。学一门语言,我认为最重要的是一方面学它的 principle,另一方面学 application。楼主有必要在学之前了解一下 C++ 的一些基本的特点,很简单:directly mapped to hardware, 还有 zero cost abstraction。楼主如果单一地照这条路走下去,很有可能会只记得前者,而忘了后者。因为 C++ 是以 directly mapped to hardware 以及与 C 语言兼容(至少是一开始)为原则而设计的,所以可以相对简单地翻译成 C 语言,但是不代表你把 C++ 代码翻译成 C 代码没问题了,C++ 代码就没问题了。如果不明白 abstraction 那一部分,那实际上没有太多用 C++ 的意义。

如果发现自己在问 std::optional 有什么意义,Template Metaprogramming 有什么用这种问题的时候,说明该去学 Haskell 压压惊了(逃
acros
2017-09-11 21:37:53 +08:00
另外你说这个反直觉我认可,颠覆 c 的认识? hmmmm 看来没见过 c 里面,0 地址强转 struct 指针求成员 offset 的那个方法。
gamexg
2017-09-11 22:11:11 +08:00
go 这样干也行,也是你只要不访问成员变量随你玩,访问了就,来😇了
admos
2017-09-11 22:31:04 +08:00
这东西各种都是 trival 的,是 POD 类型的按 c 来怎么了,还省了各种乱七八糟的呢。
douglas1997
2017-09-11 23:18:08 +08:00
@secondwtq 非常感谢前辈指导。
geelaw
2017-09-12 07:17:11 +08:00
这个程序的行为不是确定的啊,因为里面有 UB,编译器可以产生一个什么都不干的程序,也可以产生恰好输出 Hello 的程序。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/389871

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX