arm-linux-gcc编译器测试

时间:2023-03-09 00:40:41
arm-linux-gcc编译器测试

1、#include <>与#include ""的区别

  #include <>只在标准库中搜索头文件,而#include ""首先在用户工作目录(指的是当前被编译源文件所在目录)搜索,搜索不到再到标准库中搜索头文件(注意其他目录是不会搜索的)。也就是说#include ""搜索的范围比#include <>更大,但是#include <>虽然搜索范围小,但却可以节省搜索的时间。

  当我们不使用系统标准库文件,而使用自定义的库文件,这时这个自定义的文件夹(是头文件的文件夹)就替换了系统标准库,成为#include <>搜索的目录。

一个测试例子:

  假设目录test下有文件test.c 、test.h 和两个文件夹include 、lib。其中,test.c和test.h是用户程序,而include、lib是用户自定义的标准库头文件夹和源文件夹。test.c内容有这一句“#include "test.h"”,然后我们让其编译正常。这时再把test.h放到include中,我们会发现仍然编译正常。

  我们再修改test.c中这句话变成“#include <test.h>”,我们会发现仍然编译正常(这时test.h在include文件夹下)。  我们把test.h再重新放回test目录中,这时再编译就会提示找不到头文件test.h。

通过这个实验,我们就会发现我一开始说的结论。

另外,还有一种常见的格式,以一个例子说明。

  #include <mcu/asm.h>,这种情况只会搜索标准库目录(include)中mcu目录,其他目录不会搜索,包括标准库目录,也就是说这种情况只会搜索标准库目录的子目录。

  #include "mcu/asm.h",这种情况不仅要搜索标准库目录(inlcude)的子目录mcu,还要搜索用户目录的子目录mcu,而且是首先从用户目录的子目录mcu搜索。

2、文件在编译过程中只需要函数被声明,而不需要它完全被定义

一个例子:main.c内容

#include "XX.h"
int main()
{   
   wait(); 
   other_function(); 
   while ();
   return ;
}  

XX.h内容:

extern other_function(void);

说明:我们在其他源文件(.c)中定义了other_function()函数的原型,但是并没有定义wait()函数的原型。

测试:我们编译会发现会出现警告信息,说“找不到wait()函数的声明”,但是也能通过编译。

修改:XX.h

extern other_function(void);
extern wait(void);

测试:这时,我们再编译就会发现,连警告信息都没有了。

说明:显然两种情况都没有定义wait()函数的原型,所以在程序连接的时候会报错“找不到wait标号”。

     当然,如果在其他文件中定义了wait()函数,就能连接成功。

我的目的:我试图在找寻编译过程中,各个环节都是怎样工作的。

3、编译和链接做什么样的工作

  试想编译过程中就不考虑函数是否被定义,而只要声明了就能无警告信息的通过编译。说明编译过程中,主要是对本源文件(.c)中程序进行编译,而对于

外部调用的函数,实际上是链接步骤才考虑的事。

   需要说明的是,一个源文件(.c 、.S)经过编译后代码基本上已经确定,位置无关代码就是经过链接步骤也不会改变,位置有关代码才是链接器解决的问题。

  链接步骤,主要完成外部函数的相互链接,我认为是填写偏移量,或者编译地址。当然,还有全局变量的链接。

  链接步骤,会根据文件的lds文件链接程序。将每个文件的各个段按照lds文件的规定排放起来(这里我们不考虑加载地址),然后再根据外部函数的标号查找各个段,然后确定位置有关代码。当然,倘若在这里边没有定义一个段,但是却声明并使用了一个段,显然链接的时候会出现“找不到段”的错误。

  可以说,头文件主要就是外部接口的描述,把需要共享(外部调用)的段声明出来。我认为头文件在链接步骤中已经没有任何作用。