1. 几个子程序和说明
cc1 | C 的实际编译程序 |
cc1plus | C++ 的实际编译程序 |
collect2 | 在不使用 GNU 连接程序的系统上,用来产生特定的全局初始化代码 |
crt0.o | 为每个系统定制的初始化和结束代码 |
libgcc | 默认连接的 gcc 例程库 |
libstdc++ | 默认连接的 g++ 例程库 |
2. 几个重要的和 GCC 协同工作的程序,主要来自 binutils 包。
addr2line | 将文件中的调试信息翻译成为源文件的对应行号 |
ar | 用于维护目标代码的 archive,也就是创建库的程序 |
as | GNU 的汇编器 |
c++filt | 用于完成 C++ 和 Java 的 mangling/demangling |
gcov | gprof 的配置工具 |
gprof | 报告各个函数的执行时间 |
ld | GNU 的连接程序 |
nm | 列出目标文件中定义的符号 |
objcopy | 完成目标代码的复制和翻译 |
objdump | 显示目标文件的各种信息,包括代码的反汇编结果 |
ranlib | 创建和添加 ar 创建的库文件的索引 |
readelf | 获取 elf 文件信息 |
size | 列出目标文件中每部分的尺寸 |
strings | 从目标文件中析取可显示的字符串 |
strip | 从目标文件/库中去掉符号表以及其它调试使用的信息 |
3. 预处理程序,最常见的 C 使用的预处理命令,如 #define 和 #undef,
#if #elif #else #endif,#ifdef 和 #ifndef,#include,##(连接字符) 就不多说了。
#error 会引起 cpp 的中断,而 #warning 仅仅给出警告而不中断。
#pragma 主要是用于定义编译器相关的一些命令,GCC 中可用的有
#pragma GCC dependency "file" warning information
定义了该文件对 file 的时间戳依赖关系,即如 file 较当前文件新则发出警告。
#pragma GCC poison function-name
如果使用了 function-name 则发出警告。与 #pragma 等价的有 _Pragma("")
表达,这是为了在 macro 内部也能使用该功能引入的。
4. 预定义的宏
__NASE_FILE__ | 源文件的完整路径名,和 __FILE__ 不同,被引用的文件仍然是原来文件名 |
__CHAR_UNSIGNED__ | 用于指定该机器上 char 是无符号类型 |
__cplusplus | 使用 C++ 编译器编译 |
__DATE__ | 编译时的日期 |
__FILE__ | 编译文件名 |
__func__ | 同 __FUNCTION__ |
__GNUC__ | GCC 的主版本号 |
__GNUC_MINOR__ | GCC 的次版本号 |
__GNUC_PATCHLEVEL__ | GCC 的修订号 |
__GNUG__ | 由 C++ 编译程序定义 |
__INCLUDE_LEVEL__ | 指 #include 的层次 |
__LINE__ | 当前行号 |
__NO_INLINE__ | 不允许 inline |
__OPTIMIZE__ | 打开了优化选项 |
__OPTIMIZE_SIZE__ | 打开了对编译出文件尺寸的优化 |
__STDC__ | 表示该程序符合 ansi C 标准 |
__STDC_HOSTED__ | 表示宿主具有标准 C 的环境 |
__STDC_VERSION__ | 标准 C 制定时间 |
__TIME__ | 编译时系统时间 |
__VERSION__ | GCC 版本号 |
5. 在 iso646.h 中为操作符定义了 C++ 对应的操作符名称,如 and,or 等
6.产生依赖关系列表,gcc -E -M src
7. GCC 对 C 的扩展主要有,__alignof__( typename ) 返回对齐信息,可以
使用参数变长数组(在函数里面定义),同时还可以把该数组作为参数传递,
void f( int length, char buf[length] )
如果需要倒着写,需要前向声明,用分号隔开
void f( int length; char buf[length], int length )
允许结构体最后一个成员为 0 长度数组,这样可以创建变长数组。
通过 __attribute__ 可以给函数增加额外的信息便于优化,如 ((noreturn))
表明没有返回值,又如 pure 表明不会修改全局变量,noinline 表示不会 inline,
align(n) 表示执行对齐,weak,alias 连用表示是别名,always_inline 表示
总会 inline,const 不访问全局内存便于优化,constructor 是比 main 更早调用
的函数,destructor 是在 exit() 之后调用的,deprecated 表示过时了编译时发出
警告,format( style, str-pos, var-pos ) 要求编译器检查是否为 style(如 printf 和 scanf)
的函数,str-pos 是字符串参数的位置,var-pos 是可变长度参数列表的开始位置。
类似的还有 format_arg。malloc 告诉编译器其返回指针和 malloc 一样对待,
no_intrument_function 不会进行 profiling,section("sec-name") 将代码放入指定段。
类似的一些可以修饰变量,另有 mode(指定为 byte、word 或者 pointer),nocommon
(不会作为公共变量),packed(没有间隙),vector_size,类似数组。
复合语句 {} 可以返回值,用 () 包裹之,但不适用于 C++。y? y : z 可简写为 y? : z。
可以对 enum 进行声明但不定义
另有底层的三个函数,__builtin_apply_args(),__builtin_apply() 和 __builtin_return()
可以把当前函数的参数直接传递给后面的函数。
而 __builtin_return_address() 返回 ret 时应跳转的地址(frame 中第一个记录的 %ebp)
__builtin_frame_address( int ) 返回第几层的 frame 起始地址。
允许函数嵌套定义,并且该函数地址可以传递。支持 $ 命名变量名,goto 的 label 可以用
&& 取址并赋值给变量进行 goto。__label__ 可以声明局部标识为 goto 使用。只要左值表
达式产生左值(地址)即可。
可变参数宏,c99 标准为使用 ... 和 __VA_ARGS__。
在 switch 中支持 case 1 ... 9 这种表达。支持 typedet typename=var,从而将某变量的类
型定义为需要的类型。typeof(var) 产生 var 的类型。
8. C++ 里面另有 __PRETTY_FUNCTION__,而 #progma interface 和 #pragma implementation
可以表示类的性质,另有 >? 和 <? 表示返回较大较小的,并可以重载。C99 中 restruct 关键字
可以用 __restrict__。
9. C++ 中调用 C 程序只需要 external "C" 声明即可。而 C 中调用 C++ 函数也是用 external "c"
声明函数并用 g++ 编译。