Gcc对C语言的拓展功能 之 alias属性设置

以下是Gcc 8.3.0文档中的一段内容:

The following attributes are supported on most targets.

The alias attribute causes the declaration to be emitted as an alias for another symbol, which must be specified. For instance: 

defines ‘f’ to be a weak alias for ‘__f’. In C++, the mangled name for the target must be used. It is an error if ‘__f’ is not defined in the same translation unit. This attribute requires assembler and object file support, and may not be available on all targets.

翻译过来就是说,alias 属性使申明的函数作为其他符号的别名发出,即新申明的函数是“target”的别名. 在所给的示例中,将f定义为__f的弱类型别名,即弱类型符号(Weak Symbol). 在C++中必须使用名字重整(笔者注:估计是指函数的重载或者其他功能必须使用),如果__f没有在相同的翻译单元中定义将产生错误,此属性需要汇编器和目标文件支持,否则在所有目标中都不可用.

相关名词解释:

翻译单元 – Translate Unit

  • In C and C++ programming language terminology, a translation unit is the ultimate input to a C or C++ compiler from which an object file is generated. In casual usage it is sometimes referred to as a compilation unit.
  • 在C和C++的编程术语中,翻译单元是C或C++编译器的最终输入,编译后将生成目标文件。在通常的用法中一般称之为汇编单元。

名字重整 – Name mangling

  • Name mangling is the encoding of function and variable names into unique names so that linkers can separate common names in the language.
  • 名字重整是指将函数或变量名编码成唯一的名字,以便链接器能够将语言中相同的名字区分开。

弱类型符号 – Weak Symbol的定义(摘自维基):

  • Weak Symbol denotes a specially annotated symbol during linking of Executable and Linkable Format (ELF) object files. By default, without any annotation, a symbol in an object file is strong. During linking, a strong symbol can override a weak symbol of the same name. In contrast, two strong symbols that share a name yield a link error during link-time. When linking a binary executable, a weakly declared symbol does not need a definition. In comparison, (by default) a declared strong symbol without a definition triggers an undefined symbol link error.
  • 即弱符号是链接可执行文件和可链接文件格式的目标文件时特定注解的符号,没有特定注解的符号在目标文件中默认是强类型的。
  • 在链接期间,同名的强类型符号可以覆盖弱类型符号,相反,如果两个强类型符号名字相同将在链接时产生链接错误。链接可执行二进制文件时不需要定义所申明的弱类型符号。
  • 与之形成对比的是,(默认)申明的强类型符号如果没有定义将触发未定义符号链接错误。

在C语言中什么是目标文件Object file:

  • An object file is the real output from the compilation phase. It’s mostly machine code, but has info that allows a linker to see what symbols are in it as well as symbols it requires in order to work. (For reference, “symbols” are basically names of global objects, functions, etc.)A linker takes all these object files and combines them to form one executable (assuming that it can, ie: that there aren’t any duplicate or undefined symbols). A lot of compilers will do this for you (read: they run the linker on their own) if you don’t tell them to “just compile” using command-line options. (-c is a common “just compile; don’t link” option.
  • 目标文件是汇编阶段的输出文件,其内容大部分是机器码,但具有链接器正常工作所需要知道的符号信息(作为引用,符号通常是全局对象或函数名)
  • 链接器获取所有目标文件并组合形成一个可执行文件(假设其可被执行,比如:其不含重复和未定义的符号)。大部分的编译器会为我们完成组合目标文件形成可执行文件这个过程(注意到编译器以它们自己的方式运行)如果我们不以命令行的形式告知编译器仅仅编译即可的话(-c是常见的’仅编译’参数;不进行链接的选项)。

什么是预处理器,编译器,汇编器,链接器

  • (1). 预处理器(preprocessor):预处理器不止一种,而C/C++的预处理器就是其中最低端的一种——词法预处理器,主要是进行文本替换、宏展开、删除注释这类简单工作.

    gcc -E 选项可以得到预处理后的结果,扩展名为.i; C/C++预处理不做任何语法检查,不仅是因为它不具备语法检查功能,也因为预处理命令不属于C/C++语句(这也是定义宏时不要加分号的原因),语法检查是编译器要做的事情; 预处理之后,得到的仅仅是真正的源代码; GCC确实很强大,如果是用VC这种IDE,恐怕就不能看到预处理后的结果。

 

  • (2). 编译器(compiler):将文本文件.i翻译成文本文件.s,得到汇编语言程序(把高级语言翻译为机器语言),该种语言程序中的每条语句都以一种标准的文本格式确切的描述了一条低级机器语言指令。

    gcc -S 选项可以得到编译后的汇编代码,扩展名为.s; 汇编语言为不同高级语言的不同编译器提供了通用的输出语言,比如,C编译器和Fortran编译器产生的输出文件用的都是一样的汇编语言。

 

  • (3). 汇编器(Assembler):将.s翻译成机器语言指令,把这些指令打包成一种叫做可重定位目标程序的格式,并将结果保存在目标文件.o中(把汇编语言翻译成机器语言的过程)。

    gcc -c 选项可以得到汇编后的结果,扩展名为.o; .o是一个二进制文件,它的字节编码是机器语言指令而不是字符。如果在文本编辑器中打开.o文件,看到的将是一堆乱码。 把一个源程序翻译成目标程序的工作过程分为五个阶段:词法分析;语法分析;语义检查和中间代码生成;代码优化;目标代码生成。主要是进行词法分析和语法分析,又称为源程序分析,分析过程中发现有语法错误,给出提示信息。

 

  • (4). 链接器(Linker):gcc会到系统默认的搜索路径”/usr/lib”下进行查找,也就是链接到libc.so.6库函数中去。 函数库一般分为静态库和动态库两种。静态库是指编译链接时,把库文件的代码全部加入到可执行文件中,因此生成的文件比较大,但在运行时也就不再需要库文件了。其后缀名一般为”.a”。动态库与之相反,在编译链接时并没有把库文件的代码加入到可执行文件中,而是在程序执行时由运行时链接文件加载库,这样可以节省系统的开销。动态库一般后缀名为”.so”,如前面所述的libc.so.6就是动态库。gcc在编译时默认使用动态库