C++语言学习笔记之UC解析
小标 2018-07-25 来源 : 阅读 1433 评论 0

摘要:本文主要向大家介绍了C++语言学习笔记之UC解析,通过具体的内容向大家展示,希望对大家学习C++语言有所帮助。

本文主要向大家介绍了C++语言学习笔记之UC解析,通过具体的内容向大家展示,希望对大家学习C++语言有所帮助。上次提到了一个源文件要编译成一个可执行文件需要经过
1、预编译 .c->.i gcc -E .c -o .i
2、从C语言编译到汇编语言 .i->.s gcc -S .i -o .s
3、从汇编语言汇编到机器语言 .s->.o gcc -o .s -o .o
然而只汇编到机器语言是不够的,它依然无法进行执行。
汇编之后的文件叫做目标文件,目标文件可以理解为是一个具备执行条件的文件,但是不具备执行的环境。我们来对比一下可执行文件和目标文件的差异。

   

linxin@ubuntu:~/biaoc/els$ nm els.o

                 U BianJie

                 U Dir

                 U Display

                 U els_new

0000000000000191 T Get

                 U _GLOBAL_OFFSET_TABLE_

                 U InitMap

0000000000000000 T main

                 U NewBlock

                 U Next

                 U Ranking

                 U read_file

0000000000000010 T run

                 U SaoMiao

                 U srand

                 U __stack_chk_fail

                 U system

                 U time

                 U Turn

                 U write_file

linxin@ubuntu:~/biaoc/els$ nm els

0000000000001368 T BianJie

00000000002049e8 B __bss_start

00000000002049e8 b completed.7641

                 w __cxa_finalize@@GLIBC_2.2.5

0000000000203000 D __data_start

0000000000203000 W data_start

0000000000001841 T Delet

00000000000009a0 t deregister_tm_clones

0000000000001f6f T Dir

0000000000000f41 T Display

0000000000000a30 t __do_global_dtors_aux

0000000000202d50 t __do_global_dtors_aux_fini_array_entry

0000000000203008 D __dso_handle

0000000000202d58 d _DYNAMIC

00000000002049e8 D _edata

000000000000254a T els_new

0000000000203100 d elsType.1809

00000000002049f0 B _end

                 U fclose@@GLIBC_2.2.5

00000000000025d4 T _fini

                 U fopen@@GLIBC_2.2.5

0000000000000a70 t frame_dummy

0000000000202d48 t __frame_dummy_init_array_entry

0000000000002a64 r __FRAME_END__

                 U fread@@GLIBC_2.2.5

                 U fwrite@@GLIBC_2.2.5

0000000000000c0b T Get

                 U getchar@@GLIBC_2.2.5

0000000000202f48 d _GLOBAL_OFFSET_TABLE_

                 w __gmon_start__

00000000000026a0 r __GNU_EH_FRAME_HDR

0000000000000840 T _init

0000000000202d50 t __init_array_end

0000000000202d48 t __init_array_start

0000000000000d52 T InitMap

00000000000025e0 R _IO_stdin_used

                 U __isoc99_sscanf@@GLIBC_2.7

                 w _ITM_deregisterTMCloneTable

                 w _ITM_registerTMCloneTable

00000000000025d0 T __libc_csu_fini

0000000000002560 T __libc_csu_init

                 U __libc_start_main@@GLIBC_2.2.5

0000000000000a7a T main

0000000000001fdc T NewBlock

00000000000021a3 T Next

                 U printf@@GLIBC_2.2.5

                 U putchar@@GLIBC_2.2.5

                 U rand@@GLIBC_2.2.5

00000000000021f6 T Ranking

000000000000245f T read_file

00000000000009e0 t register_tm_clones

0000000000000a8a T run

0000000000001911 T SaoMiao

                 U sprintf@@GLIBC_2.2.5

                 U srand@@GLIBC_2.2.5

                 U __stack_chk_fail@@GLIBC_2.4

0000000000000970 T _start

                 U strncat@@GLIBC_2.2.5

                 U system@@GLIBC_2.2.5

                 U time@@GLIBC_2.2.5

00000000002049e8 D __TMC_END__

0000000000001b2e T Turn

0000000000203020 d TurnR.2787

00000000000010c4 T UpData

0000000000002321 T write_file

   

可以看到,在目标文件中所有的标记都是自定义的函数,其中有些函数的属性是T,有些是U
T:表示这个文件调用了这些函数,而且这些函数的定义在本文件内
U:表示这个文件调用了这些函数,但是这些函数不在本文件内
而在可执行文件中,所有自定义的函数的属性都变成了T,还增加了许多没有见过的标记。
这就是可执行文件内容和目标文件内容的差异,也描述了链接过程,做了什么。
链接的过程大概如下,有一堆.o的二进制文件要进行链接的时候,首先找到main函数所在,然后一条一条的从mian函数所在文件向下扫描,当碰到一个U属性的函数,就到定义这个函数的文件里,把这个文件所有的内容全部加载。一直重复这个动作,直到main函数结束。然后再加上运行时文件,最后生成一个可执行文件。
那么什么是运行时文件?
这些文件更像是一种引导,用户写好的程序其实是一个独立的个体,想要再操作系统上运行,必须具备相应的环境,而这些运行时文件,就相当于给客户的程序装上一个运行的环境。引导我们写好的程序进入操作系统运行。
这就是一个链接的过程:
链接分为静态链接和动态链接。
上述的过程是一个静态链接的过程。
静态链接发生在生成可执行文件的时候
动态链接发生在可执行文件运行的时候
在我们的可执行文件中,依然存在着一些U属性的函数,这些函数,就是运行时会动态链接上来的函数。

大型软件的组织
一个团队进行一个大型软件的开发,需要遵循一定的标准。标准里规定某一部分完成某一个具体的工作,需要为其提供什么要的参数,需要其返回什么样的参数。这些标准都通过头文件里,让每一个参与开发的人员都知道自己需要做什么。
头文件中可以包含任意不需要内存的东西,具体可以包括以下几种:
#ifndef HEAD_H
#define HEAD_H
类型的定义
变量的声明
宏定义
文件的包含
#endif
在这里有个非常颠覆三观的概念,函数也是一种类型
struct str{
int (*func)(struct str *this);
}

GDB调试工具的使用,(这个东西超级好用)
对一个拥有调试信息的程序可以使用GDB工具对其进行调试
对源文件编译的时候,加上-g|-ggdb的选项就可以对最后生成的可执行文件加入调试信息
在bash中输入 : gdb 带有调试信息的可执行程序名
gdb a.out(可执行文件)
gdb 调试命令
l 列出程序列表
b (后面跟函数的名字,或者行数) 设置断点
r 开始运行
n 继续下一行执行
p (后面跟变量的名字,查看变量当前的值)
s 继续下一步执行
q 退出
可以使用man来查看gdb拥有的参数,
它可以运行到指定的程序函数|行数,可以输出当前这个变量内的值。
还有非常多的花样可以玩

一个静态库的制作和使用
1、把所有要放进静态库的文件,编译成目标文件 gcc -c .c
2、将所有的目标文件都打包进静态库 ar -r libels(lib+库名) els1.o els2.o els3.o(要放入静态库的目标文件名称)
3、编译时,使用静态库 gcc els.c -L.(静态库所在路径) -lels(-l+库名,不是库文件名)
ar也是个有趣的指令,可以通过man查看它的资料,非常的多。

#include”“,
这里有几种解决头文件位置的方法。
1、在include后面的”“中存放的时头文件的位置,可以把头文件的位置放进去
#include”els/els.h” ,表示头文件在当前同级目录els下
2、在进行编译的时候,可以临时的为编译器增加一条寻找头文件的路径
gcc -c els.c -Iels
这样就可以把路径加进去了,可以来看以下加与不加的效果 

linxin@ubuntu:~/biaoc$ gcc -c els.c -v

...

#include "..." search starts here:

#include <...> search starts here:

 /usr/lib/gcc/x86_64-linux-gnu/7/include

 /usr/local/include

 /usr/lib/gcc/x86_64-linux-gnu/7/include-fixed

 /usr/include/x86_64-linux-gnu

 /usr/include

End of search list.

...

 

 

linxin@ubuntu:~/biaoc$ gcc -c els.c -Iels -v

...

#include "..." search starts here:

#include <...> search starts here:

 els

 /usr/lib/gcc/x86_64-linux-gnu/7/include

 /usr/local/include

 /usr/lib/gcc/x86_64-linux-gnu/7/include-fixed

 /usr/include/x86_64-linux-gnu

 /usr/include

End of search list.

...

   

加了指令之后,系统指定的头文件目录路径就多了一条
3、还可以直接把头文件,放在系统指定的头文件路径之下,不过这么做可能会污染系统头文件,所以一定要这么做的时候,要记得对自定义的头文件的命名一定要规范。

本文由职坐标整理并发布,希望对同学们有所帮助。了解更多详情请关注职坐标编程语言C/C+频道!

本文由 @小标 发布于职坐标。未经许可,禁止转载。
喜欢 | 1 不喜欢 | 0
看完这篇文章有何感觉?已经有1人表态,100%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程