macOS 中神秘的 GCC
最近在看人工智能相关的知识,无意中发现了一个巨牛的 人工智能教程,分享一下给大家。
教程不仅是零基础,通俗易懂,而且非常风趣幽默,像看小说一样!觉得太牛了,所以分享给大家。点 这里 可以直接看教程。
这个事情,要从编译一个简单的代码开始说起。
gcc 和 g++ 的区别
gcc
是 GCC 中的 GUN C Compiler,C 编译器。
g++
是 GCC 中的 GUN C++ Compiler,C++编译器。
就本质而言,gcc
和 g++
并不是编译器,也不是编译器的集合,它们只是一种驱动器,根据参数中要编译的文件的类型,调用对应的 GUN 编译器而已。
gcc
与 g++
都可以编译 C 和 C++ 文件,只是处理方式不同。 可以参考 GCC的gcc和g++区别 这篇文章。
交换变量:用指针
下面这段代码很简单,利用 C 指针实现交换两个变量的目的。
源文件:mz_swap.c
1 |
|
在 macOS 下使用 gcc
编译 mz_swap.c
,产生可执行文件 exec_main.out
,如下操作:
1 | gcc mz_swap.c -o exec_main.out |
编译成功,执行 ./exec_main.out
,正常输出结果:
1 | --Before-- xp = 901, yp = 902 |
采用 g++ 来编译,如下操作:
1 | g++ mz_swap.c -o exec_main.out |
报出如下警告,该警告的意思是在 C++ 模式下强制编译 C 文件,这里可以不予理会。
1 | clang: warning: treating 'c' input as 'c++' when in C++ mode, this behavior is deprecated [-Wdeprecated] |
虽然有警告,但是编译可以产生可执行文件 exec_main.out
且可以正常执行的,执行结果跟上面一样。
交换变量:用引用
大家都知道,C 没有 引用
这个概念,而 C++ 是有 引用
概念的,可以在此了解 C++ 引用.
试一下使用 gcc
编译使用 引用
方式编写的 C 代码,按照说法,gcc
是无法编译通过的。
源文件:mz_swap_ref.c
1 |
|
编译
1 | gcc mz_swap_ref.c -o exec_main.out |
编译失败,错误信息如下:
1 | mz_swap_ref.c:4:21: error: expected ')' |
既然按照 C 的编译方式不行,那就换成 g++
来编译。
1 | g++ mz_swap_ref.c -o exec_main.out |
编译成功,执行可执行文件
1 | ./exec_main.out |
1 | --Before-- xp = 901, yp = 902 |
大家可以自己动手试试,使用 clang 来编译 mz_swap_ref.c
和使用 gcc
来编译都是报错,使用 clang++
和 g++
编译都是没有问题的。
在博客 GCC: Homebrew 安装 GCC 和 Binutils 中,我已经分享了在 macOS 中的 gcc
和 g++
不是 GNU 提供的,而是 Apple 自己的 clang。
这里要说明的是即使使用自己安装的 gcc(gcc-4.9
) 来编译 mz_swap_ref.c
也是无法编译通过的,验证如下:
1 | gcc-4.9 mz_swap_ref.c -o exec_main.out |
错误信息:
1 | mz_swap_ref.c:4:21: error: expected ';', ',' or ')' before '&' token |
gcc、g++ 和 clang 的关系
在 macOS 中,gcc
以某种方式指向 llvm-gcc
编译器,g++
亦如此。
1 | In Apple's version of GCC, both cc and gcc are actually symbolic links to the llvm-gcc compiler. Similarly, c++ and g++ are links to llvm-g++. |
llvm-gcc
是 c/c++/oc 的编译器,用了 gcc
前端和命令行界面的 llvm.
1 | llvm-gcc is a C, C++, Objective-C and Objective-C++ compiler. llvm-g++ is a compiler driver for C++. llvm-gcc uses gcc front-end and gcc's command line interface. |
接下来,我们看一下 llvm-gcc
,可以使用 which llvm-gcc
看一下 llvm-gcc
所在位置是 /usr/bin/llvm-gcc
,打开目录可以看出其实是一个符号链接,如下图所示:
1 | ls -l /usr/bin/llvm-gcc |
1 | /usr/bin/llvm-gcc -> clang |
它们是统一指向 clang
的符号链接,可以看其原始指向,llvm-gcc
指向 clang
,llvm-g++
指向 clang++
。
二者都在 /usr/bin/
目录下:
其实在 macOS 中 cc
编译器也指向 clang
。
总结
通过上面的例子,我们至少可以学到如下几点知识:
1、C 语言规范中没有 引用
的概念,使用 C 编译器无法使其编译通过,但是使用 C++ 编译器是可以编译通过的。这是因为各自的编译器是遵循语言规范的。
2、macOS 中的 gcc
和 g++
苹果开发者们并没有去改造和重写它们,只是分别指向 clang
和 clang++
编译器。
3、如果不想使用 macOS 中的 gcc
和 g++
,就需要自己重新安装 GNU 的编译套件,安装和使用方法已经在博客中有说明。
扫码关注,你我就各多一个朋友~