伊犁建设网站公司深圳开发公司网站建设比较好的

张小明 2026/1/1 3:14:28
伊犁建设网站公司,深圳开发公司网站建设比较好的,开发直播软件需要多少钱,移动网站源码#x1f3ac; 个人主页#xff1a;Vect个人主页#x1f3ac; GitHub#xff1a;Vect的代码仓库#x1f525; 个人专栏: 《数据结构与算法》《C学习之旅》《Linux》⛺️Per aspera ad astra. 文章目录1. C如何从代码到可执行文件1.0. 一小段代码进行演示1.1. 预处理阶段: g… 个人主页Vect个人主页 GitHubVect的代码仓库 个人专栏: 《数据结构与算法》《C学习之旅》《Linux》⛺️Per aspera ad astra.文章目录1. C如何从代码到可执行文件1.0. 一小段代码进行演示1.1. 预处理阶段: g -E1.2.编译阶段g -S1.3. 汇编阶段g -c1.4. 链接阶段g main.o foo.o -o app1.5. 把模板定义放到.cpp会发生什么2. 动态库和静态库2.1. 动态库2.2. 静态库2.3. 二者对比3. 总结1. C如何从代码到可执行文件1.0. 一小段代码进行演示// add.h#pragmaoncetemplateclassTTadd(T a,T b){returnab;}// foo.cpp#includeadd.hintfoo(){returnadd(10,30);// addint实例化}// main.cpp#includeadd.h#includeiostreamusingnamespacestd;intfoo();intmain(){coutadd(1,2)endl;coutfoo()endl;return0;}1.1. 预处理阶段:g -E预处理阶段编译器只做文本级工作展开#include把头文件的内容拷贝进来宏替换#define条件编译#if/#ifdef去掉注释注意模板实例化不在预处理阶段预处理器不懂C语义只做文本级处理命令演示[vectVM-0-11-centos ~]$ g -E main.cpp -o main.i[vectVM-0-11-centos ~]$ g -E foo.cpp -o foo.i-E:只执行预处理操作预处理结束就停止-o指定输出文件名后面紧跟文件名filename.i预处理后的源文件后缀为.i如果不加-o main.i预处理过后的文件会输出到终端1.2.编译阶段g -S把预处理后的.i文件变成汇编文件.s词法/语法分析把字符流变成token流我们写的代码对于机器来说就是一串字符编译器会把这串字符组合成有意义的”单词“即token流判断token流的排列是否符合C语法并构建AST树(抽象语法树)写的一行代码int a b 3;在计算机眼里就是一串字符i n t a b 3 ;,现在把这些字符组成有意义的token具体包括了关键字、标识符、运算符、字面量、语句结束符这个阶段只关心”单词的构建“不关系语法是否正确现在已经形成token流[int] [a] [] [b] [] [3] [;]语法分析的结果不是对与错而是构建AST树这句代码真正的结构含义 / \ a / \ b 3然后补充上类型信息声明语句 ├──类型:int └── 赋值 ├──变量:a └── 加法 ├──变量:b └──常量:3这里可以类比词法分析-认识单词 语法分析-分析句子主谓宾 AST-句子的语法树状图语义分析类型检查、重载检查、名字查找、访问控制、模板相关规则模板实例化当编译器看到”需要用到的模板“时会生成具体版本的函数体例如add(1,2)---addint(int,int)优化基于AST树修改AST树常量折叠(直接进行运算不留到运行期int x 5 3 - int x 8)、内联直接替换函数调用在这里展开函数内联只是建议、死代码删除删除永远不会执行的代码、寄存器分配…生成汇编输出.s命令演示[vectVM-0-11-centos ~]$ g -S main.i -o main.s[vectVM-0-11-centos ~]$ g -S foo.i -o foo.s可以观察到此时已经形成了汇编代码1.3. 汇编阶段g -c汇编把.s汇编代码变成机器码目标文件二进制文件.o二进制文件包含.text段机器指令.rodata只读常量.data/.bss全局/静态数据符号表目标文件中定义了哪些符号、还需要外部提供哪些符号符号函数名、全局变量名、静态变量名符号表**目标文件里的一张”名字-状态/地址“**的表回答定义了哪些符号使用了哪些符号但是还不知道地址举个例子理解一下// show_signal.cppintfoo(){return23;}编译[vectVM-0-11-centos ~]$ g -c show_signal.cpp -o foo.o[vectVM-0-11-centos ~]$ nm -C foo.o# 查看符号表U __cxa_atexit U __dso_handle 0000000000000048 t _GLOBAL__sub_I__Z3foov 0000000000000000 T foo()000000000000000b t __static_initialization_and_destruction_0(int, int)U std::ios_base::Init::Init()U std::ios_base::Init::~Init()0000000000000000 b std::__ioinit0000000000000000 T foo()偏移地址 在.text段中定义 符号名说明了在foo.o里面自己定义了foo再看需要外部提供符号的情况intfoo();// 声明未定义intmain(){returnfoo();}编译[vectVM-0-11-centos ~]$ g -c main_signal.cpp -o main.o[vectVM-0-11-centos ~]$ nm -C main.o U __cxa_atexit U __dso_handle 0000000000000048 t _GLOBAL__sub_I_main 0000000000000000 T main U foo()000000000000000b t __static_initialization_and_destruction_0(int, int)U std::ios_base::Init::Init()U std::ios_base::Init::~Init()0000000000000000 b std::__ioinit看这段代码0000000000000000 T main U foo()U undefined未定义这里说明在mian.o中用到了foo()但是在mian.o中没有实现需要外部提供的符号所以符号表的作用当链接器拿到main.o发现需要foo而foo.o定义了foo则指向foo.o里的foo地址重定位信息哪些地址等链接时再决定一个残酷的事实在.o文件中所有地址都是临时的因为.o不知道将来和谁链接不知道程序从内存哪里开始所以编译器只能做到将来这里要用一个地址我先占个坑举个例子intfoo();// 声明未定义intmain(){returnfoo();}在汇编层面call _Z3foov这里foo被改名为_Z3foov这里可以补充一个知识点为什么C支持函数重载在汇编和链接层面名字必须唯一C函数会进行函数名改编把函数名编进符号表里_Z 3 foo v │ │ │ │ │ │ │ └── 参数列表v void无参数 │ │ └─────── 函数名 foo │ └─────────── 3 表示 foo 这个名字长度是 3 └─────────────── _Z C 符号前缀voidfoo();// _Z3foovvoidfoo(int);// _Z3fooivoidfoo(double);// _Z3food常见的类型编码类型编码voidvintidoubledcharclongl指针P这里我们也可以用nm main_signal.o来查看编译器如何解决这个问题生成机器码留一个备注重定位信息重定位表是啥一张需要补地址的清单总结一下在汇编阶段编译器的行为收集所有符号表-给所有符号分配最终地址-处理重定位的信息而符号表表达了谁是谁重定位信息表达了地址填哪1.4. 链接阶段g main.o foo.o -o app编译器把多个.o文件包括库文件.a/.so拼成一个可执行文件或共享库符号解析把main.o里未定义的符号去别的.o/.a/.so里找定义地址分配和段合并把各个.text/.data合并给每个符号分配最终地址重定位把机器码/数据中”占位“的地址改成最终地址处理库依赖静态库.a把需要的目标文件成员抽取进行最终程序动态库.so记录依赖关系运行时由动态装载器加载命令演示[vectVM-0-11-centos link]$ g main.o foo.o -o app[vectVM-0-11-centos link]$ ./app[vectVM-0-11-centos link]$ ldd ./app# 查看依赖的动态库linux-vdso.so.1(0x00007ffd751fe000)libstdc.so.6/home/vect/.VimForCpp/vim/bundle/YCM.so/el7.x86_64/libstdc.so.6(0x00007ff731b8b000)libm.so.6/lib64/libm.so.6(0x00007ff731889000)libgcc_s.so.1/lib64/libgcc_s.so.1(0x00007ff731673000)libc.so.6/lib64/libc.so.6(0x00007ff7312a5000)/lib64/ld-linux-x86-64.so.2(0x00007ff731f0c000)1.5. 把模板定义放到.cpp会发生什么add.h只写声明// add.h#pragmaoncetemplatetypenameTTadd(T a,T b);// 只有声明没有定义add.cpp定义模板// add.cpp#includeadd.htemplatetypenameTTadd(T a,T b){returnab;}// main.cpp#includeiostream#includeadd.hintmain(){std::coutadd(1,2)std::endl;return0;}编译每个cpp都成功了[vectVM-0-11-centos template]$ g -c add.cpp -o add.o[vectVM-0-11-centos template]$ g -c main.cpp -o main.o这里已经埋雷了链接出错[vectVM-0-11-centos template]$ g add.o main.o -o app main.o: Infunctionmain: main.cpp:(.text0xf): undefined reference toint addint(int, int) collect2: error: ld returned1exitstatus为什么会出错编译main.cpp发生了什么​add(1,2);编译器知道这是个模板需要生成addint函数体但在add.h里只看到声明没有定义于是编译器只能假设将来有人实现addint在mian.o里符号表是U int addint(int, int)编译add.cpp发生了什么[vectVM-0-11-centos template]$ nm -C add.o[vectVM-0-11-centos template]$符号表是空的在add.cpp里没有任何地方用到addint编译器遵循模板哪里使用哪里实例化的原则链接发生了什么文件情况main.o我需要addintadd.o我没定义addint现在没人提供这个符号报错undefined reference to int addint(int, int)本质说明了模板的实例化发生在编译期而不是链接期所以怎么解决模板定义放在头文件在add.cpp文件中显式实例化2. 动态库和静态库动态库用的时候程序只记住去哪里找真正运行时再加载静态库用的时候把代码直接拷贝到程序里我们还是用add这份代码不要模板2.1. 动态库Linux下.so为后缀的文件本质是独立存在的二进制文件怎么生成生成位置无关代码g -fPIC add.cpp -o add.o-fPIC告诉编译器这段代码将来被共享生成动态库g -shared add.o -o libadd.so生成了动态库libadd.so动态库链接g main.cpp -L. -ladd -o app_dynamic-L.:在当前目录找库-ladd优先找libadd.so验证依赖ldd app_dynamic完整代码[vectVM-0-11-centos rep]$ g -fPIC -c add.cpp -o add.o[vectVM-0-11-centos rep]$ g -shared add.o -o libadd.so[vectVM-0-11-centos rep]$ g main.cpp -L. -ladd -o app_dynamic[vectVM-0-11-centos rep]$ g main.cpp -L. -ladd -o app_dynamic[vectVM-0-11-centos rep]$ ./app_dynamic3[vectVM-0-11-centos rep]$ ldd app_dynamic linux-vdso.so.1(0x00007ffe6c5bd000)libadd.so(0x00007fdfcef90000)libstdc.so.6/home/vect/.VimForCpp/vim/bundle/YCM.so/el7.x86_64/libstdc.so.6(0x00007fdfcec0f000)libm.so.6/lib64/libm.so.6(0x00007fdfce90d000)libgcc_s.so.1/lib64/libgcc_s.so.1(0x00007fdfce6f7000)libc.so.6/lib64/libc.so.6(0x00007fdfce329000)/lib64/ld-linux-x86-64.so.2(0x00007fdfcf192000)动态库编译时只记住地址运行时再加载代码2.2. 静态库Linux下.a为后缀的文件本质是一堆.o文件的打包怎么生成编译成目标文件g -c add.cpp -o add.o此时add.o里面有add的机器码还没有生成程序打包成静态库ar rcs libadd.a add.o现在有静态库libadd.a链接生成可执行程序g main.cpp libadd.a -o app_staticmain.cpp用了addlibadd.a里刚好有add.o直接把add.o复制进最终程序查看依赖ldd app_static会发现没有libadd.a,其实代码已经拷贝到程序里了完整代码[vectVM-0-11-centos rep]$ g -c add.cpp -o add.o[vectVM-0-11-centos rep]$ ar rcs libadd.a add.o[vectVM-0-11-centos rep]$ g main.cpp libadd.a -o app_static[vectVM-0-11-centos rep]$ ./app_static3[vectVM-0-11-centos rep]$ ldd app_static linux-vdso.so.1(0x00007ffd18faa000)libstdc.so.6/home/vect/.VimForCpp/vim/bundle/YCM.so/el7.x86_64/libstdc.so.6(0x00007f51a6245000)libm.so.6/lib64/libm.so.6(0x00007f51a5f43000)libgcc_s.so.1/lib64/libgcc_s.so.1(0x00007f51a5d2d000)libc.so.6/lib64/libc.so.6(0x00007f51a595f000)/lib64/ld-linux-x86-64.so.2(0x00007f51a65c6000)静态库编译时把代码拷贝到而可执行文件2.3. 二者对比对比点静态库动态库add 的代码拷进 app在 libadd.so可执行文件大小ldd看不到 add能看到 libadd.so运行依赖无必须有 so3. 总结
版权声明:本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

自己做网站推广需要多少钱怎么制作公众号推文

3.1 功率同步控制与下垂控制 构网型变流器的核心在于其能够作为自主的电压源,建立并支撑电网的电压和频率。在众多构网控制策略中,功率同步控制 和 下垂控制 是两种基础且应用最为广泛的经典方法。它们在实现电压源外特性的具体路径上有所不同,但都旨在通过模拟同步发电机的…

张小明 2025/12/29 0:34:21 网站建设

小程序开发费用分析网站架构优化

第一章:安卓手机也能跑AutoGLM?初探本地AI的可行性随着大模型技术的普及,越来越多开发者开始探索在移动设备上运行本地化AI推理的可能性。安卓手机凭借其开放的系统架构和不断升级的硬件性能,正逐步成为轻量级AI模型部署的新平台。…

张小明 2025/12/30 5:32:21 网站建设

织梦个人网站模版网站备案怎么改

5个技巧彻底释放小爱音箱音乐播放潜力 【免费下载链接】xiaomusic 使用小爱同学播放音乐,音乐使用 yt-dlp 下载。 项目地址: https://gitcode.com/GitHub_Trending/xia/xiaomusic 还在为小爱音箱的音乐播放限制而烦恼吗?XiaoMusic作为一款专为小爱…

张小明 2025/12/29 13:53:45 网站建设

惠州做网站首选惠州邦大连网龙

Windows字体终极美化指南:3步实现专业级渲染效果 【免费下载链接】mactype Better font rendering for Windows. 项目地址: https://gitcode.com/gh_mirrors/ma/mactype 想要让Windows系统的字体显示效果达到专业水准吗?通过本指南,你…

张小明 2025/12/29 15:40:15 网站建设

广西医科大学网站建设软件实施的五个步骤

高薪计算机视觉进阶指南:单双目视觉深度估计一站式通关 引言:深度估计——开启三维视觉世界的钥匙 在计算机视觉的黄金赛道上,深度估计技术正成为高薪岗位的核心竞争力。从自动驾驶的精准感知到AR/VR的沉浸体验,再到工业检测的毫…

张小明 2025/12/30 1:03:25 网站建设

网站流量带宽网站访客qq系统

企业级Visio迁移革命:drawio-desktop跨平台图表解决方案实战指南 【免费下载链接】drawio-desktop Official electron build of draw.io 项目地址: https://gitcode.com/GitHub_Trending/dr/drawio-desktop 在全球数字化转型加速推进的当下,企业I…

张小明 2025/12/30 3:59:14 网站建设