gcc是Linux/Unix上非常强大的C语言编译器。并且如今也支持C++的编译。与VC不同,gcc是完全跨平台的。到目前为止很多工具都使用gcc作为其编译环境,比如cocos2d-x,android的NDK等等。 学习使用gcc编译器,就是学习它众多的编译参数。就是用连字符-连接的参数.
因为它的参数并不全是单字符的,所以不能使用一个连字符后加多个参数的写法, 要每个参数前面都要加一个连字符.

常用用法

直接在gcc后面加上要编译的C语言源文件
gcc hello.c
这种默认的情况下会生成一个名为a.out的可执行文件。
-o 最常用的编译选项,用于指定要生成的可执行文件的名称。
gcc -o hello hello.c
需要体会的一点是:gcc对于参数的位置无要求!比如也可以写作
gcc hello.c -o hello
惟一要注意的就是-o后面一定要紧跟要生成的可执行文件名。
-g 用于给生成的可执行文件加上调试信息,只有这样才可使用gdb调试。
gcc -g -o hello hello.c
同样参数-g的也可写在hello.c后面。

-D选项
参考如下代码great.c

#include <stdio.h>
int main(int argc, char *argv[])
{
#ifdef MYDEBUG
    printf("test\n");
#endif
    printf("hello world\n");

    return 0;
}

如果我想要让程序打印test,测试该分支运行情况可以用如下命令:
gcc -D MYDEBUG -g -o great great.c
(gcc -DMYDEBUG -g -o great great.c ) -D后面直接紧跟我们需要定义的宏也是正确的。
当我们需要指定值的时候,可以使用如下命令:
gcc -DMYDEBUG=10 -g -o great great.c ,此处需要注意的是MYDEBUG=10之间不能有空格,原因是shell语法存在此限制。
./great
如果直接
gcc -o great great.c
./great
程序执行结果:

通过使用—D选项可以测试程序分支的正确与否,验证程序的逻辑正确性.

华丽的分割线

选项 -E
gcc -E test.c -o test.i 将test.c预处理输出test.i文件。
另一种形式
gcc -E test.c >test.i,如果不重定向到test.i,则会在标准输出中显示,例如直接执行gcc -E test.c
选项 -S
gcc -S test.i 将预处理输出文件test.i汇编成test.s文件。
选项 -c
gcc -c test.s 将汇编输出文件test.s编译输出test.o文件。

多文件编译与Makefile

1.多个文件一起编译
用法:gcc a.c b.c c.c d.c -o main
作用:将多个.c文件编译后链接成可执行文件 ./main执行
2.单独编译各个源文件,然后对编译后的.o文件进行链接
gcc -c a.c //生成a.o
gcc -c b.c //生成b.o
gcc -c c.c //生成d.o
gcc -c d.c //生成d.o
例子:
display.c

#include <stdio.h>
void display(const char *str)
{
    printf("hello world :%s.\n",str);
}

main.c

#include <stdio.h>
extern func();
int main()
{
    display("52coder");
    return 0;
}

关于在main.c中extern func()是告诉编译器func()声明在别的文件,如果不加这一行的话会有如下告警:
main.c:5:5: warning: implicit declaration of function ‘display’

使用c99标准编译 默认的情况下,编译器是以c89的标准编译的。使用c99则:
gcc -std=c99 hello.c

-O选项

Optimization
-O0
禁止编译器进行优化。默认为此项。
-O
-O1
尝试优化编译时间和可执行文件大小。
-O2
更多的优化,会尝试几乎全部的优化功能,但不会进行“空间换时间”的优化方法。
-O3
在 -O2 的基础上再打开一些优化选项:-finline-functions, -funswitch-loops 和 -fgcse-after-reload 。
-Os
对生成文件大小进行优化。它会打开 -O2 开的全部选项,除了会那些增加文件大小的。

共享库

最后要重点说说这个共享库,在没有翻APUE之前我对共享库的理解始终停留在理论阶段,直到看到APUE这本书,感谢当初送这本书给我的同学,虽然我已经忘记是谁毕业送(丢)给我的了!这真的是一本好书!
现在大多数UNIX系统支持共享库。共享库使得可执行文件中不再需要包含公用的库函数,而只需在所有进程都可引用的存储区中保存这种库例程的一个副本。程序第一次执行或者第一次调用某个库函数时,用动态链接方法将程序与共享库函数相链接。这减少了每个可执行文件的长度,但增加了一些运行时间开销。这种时间开销发生在该程序第一次被执行时,或者每个共享库函数第一次被调用时。共享库的另一个优点是可以用库函数的新版本代替老版本而无需对使用该库的程序重新连接编辑(假设参数的数目和类型都没有发生改变)。
在不同的系统中,程序可能使用不同的方法说明是否要使用共享库。比较经典的是cc和gcc命令的选项。作为长度方面发生变化的例子,先用无共享库方式创建下列代码的可执行文件。可以通过下面的执行过程看出,使用共享库编译此程序,可执行文件的text代码段 data数据段 bss未初始化的数据段大小均大幅度减小。
gcc中使用-static的作用是阻止gcc使用共享库。

#include <stdio.h>
int main()
{
    printf("Hello,world\n");
    return 0;
}

gcc使用不同版本C语言编译程序

GNU编译器(GNU Comoiler Collection,GCC)可以基于不同的命令行选项,依照多个不同版本的C语言规则来编译程序。例如根据iSO C11来编译程序prog.c可以使用如下命令:
gcc -std=c11 prog.c
使用GCC指定不同的C语言版本
```

C 版本 GCC命令行选项
GNU 89 无,-std=gnu89
ANSI,ISO C90 -ansi,-std=c89
ISO C99 -std=c99
ISO C11 -std=c11

大多数64位机器能够运行32位机器编译的程序,这是向后兼容。可以使用
gcc -m32 prog.c
gcc -m64 prog.c
使用-m32编译后的程序可以在32位 64位机器下运行,使用-m64编译后只能在64位机器上运行。 

gcc -Og -S mstore.c
编译选项-Og告诉编译器使用会生成符合原始C代码整体结构的机器代码的优化等级。使用较高级别优化产生的代码会严重变形,以至于产生的机器代码和初始源代码之间的关系非常难以理解。
gcc -g -Wall -v hello.c -o hello
使用-v选项可以查看完整和详细的编译过程。

使用gdb时,使用p命令打印一个(void *)变量时会报如下错误:
Attempt to dereference a generic pointer.
此时,只需要将(void *)变量强制类型转化成需要打印的类型,使用p命令即可打印。
例如,需要打印(struct counter64 *)型val_str变量,则使用命令格式:
p *(struct counter64 *)val_str

####gcc参数

$ gcc -save-temps main.c

$ ls
a.out main.c main.i main.o main.s
```
使用 -save-temps选项可以看到编译生成的全部中间文件。