ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

C/C++之从源文件到可执行程序

2019-03-18 15:38:14  阅读:363  来源: 互联网

标签:function msg1 msg2 C++ hello 源文件 declaration main 可执行程序


搬运自我的CSDN https://blog.csdn.net/u013213111/article/details/88537509

学习了一下makefile的写法,跟我一起写 Makefile(一),顺便看看源文件是怎么变成可执行程序的。
GCC干了些什么事情呢?在CSAPP的1.2节中讲得很清楚了:


gcc有四个阶段:预处理——编译——汇编——链接。于是在makefile中可以明显地看到最终的可执行目标程序依赖于一堆.o文件(可重定位目标程序),这一堆.o文件是由链接器ld来进行组合打包的,而.o文件又依赖于对应的.c文件(源文件)。
所以,假如有多个源文件,例如有main函数在hello.c中,在main函数中又分别调用了位于msg1.c和msg2.c中的msg1函数和msg2函数,那么gcc在编译hello.c的过程中其实是“不涉及”msg1.c和msg2.c文件的,要用gcc hello.c msg1.c msg2.c -o hello这样的命令分别生成三个源文件对应的.o文件,再由链接器把.o文件们打包组合成hello这个可执行程序。
那么就有个地方要注意了:在C语言中,函数在调用前不一定非要声明。如果没有声明,那么编译器会自动按照一种隐式声明的规则,为调用函数的C代码产生汇编代码。
会产生什么样的问题呢?参考万恶之源:C语言中的隐式函数声明,当隐式声明函数名称恰好在链接库中存在,但返回非int类型时,就会导致错误。所以呢,强烈建议程序员重视编译器给出的关于隐式声明的警告,及时通过包含必要的头文件来消除这种警告

来看看实例吧:

1 //hello.c
2 #include <stdio.h>
3 int main()
4 {
5     printf("Hello, world!\n");
6     msg1();
7     msg2();
8     return 0;
9 }
1 //msg1.c
2 #include <stdio.h>
3 void msg1(void)
4 {
5     printf("the message sent from msg1\n");
6 }
1 //msg2.c
2 #include <stdio.h>
3 void msg1(void)
4 {
5     printf("the message sent from msg2\n");
6 }

在hello.c中没有声明msg1和msg2这两个函数,用gcc hello.c msg1.c msg2.c -o hello命令得到这样的警告:

hello.c: In function ‘main’:
hello.c:5:3: warning: implicit declaration of function ‘msg1’ [-Wimplicit-function-declaration]
   msg1();
   ^
hello.c:6:3: warning: implicit declaration of function ‘msg2’ [-Wimplicit-function-declaration]
   msg2();
   ^

但是仍然生成了hello可执行文件,执行一下,输出正常:

Hello, world!
the message sent from msg1
the message sent from msg2

那么假如在编译的时候没有加入msg2.c会提示什么呢?gcc hello.c msg1.c -o hello看看,除了之前的警告信息外,还有error: ld returned 1 exit status,链接器ld找不到要依赖的文件了。

hello.c: In function ‘main’:
hello.c:5:3: warning: implicit declaration of function ‘msg1’ [-Wimplicit-function-declaration]
   msg1();
   ^
hello.c:6:3: warning: implicit declaration of function ‘msg2’ [-Wimplicit-function-declaration]
   msg2();
   ^
/tmp/ccYSfgV0.o: In function `main':
hello.c:(.text+0x27): undefined reference to `msg2'
collect2: error: ld returned 1 exit status

上面提到的隐式函数声明,在C++中是没有的,对未声明的函数进行调用会无法通过编译,把gcc改为g++再来试试,g++ hello.c msg1.c msg2.c -o hello,果然error了:

hello.c: In function ‘int main()’:
hello.c:5:8: error: ‘msg1’ was not declared in this scope
   msg1();
        ^
hello.c:6:8: error: ‘msg2’ was not declared in this scope
   msg2();
        ^

对了,关于头文件和源文件的关系还有一篇文章可以参考:.c和.h文件的区别

标签:function,msg1,msg2,C++,hello,源文件,declaration,main,可执行程序
来源: https://www.cnblogs.com/lyrich/p/10552471.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有