思考:为什么函数模板可以和函数重载放在一块。C++编译器是如何提供函数模板机制的?

一、编译器编译原理

什么是gcc

gcc(GNU C Compiler)编译器的作者是Richard Stallman,也是GNU项目的奠基者。

什么是gcc:gcc是GNU Compiler Collection的缩写。最初是作为C语言的编译器(GNU C Compiler),现在已经支持多种语言了,如C、C++、Java、Pascal、Ada、COBOL语言等

gcc支持多种硬件平台,甚至对Don Knuth 设计的 MMIX 这类不常见的计算机都提供了完善的支持

gcc主要特征

1)gcc是一个可移植的编译器,支持多种硬件平台

2)gcc不仅仅是个本地编译器,它还能跨平台交叉编译。

3)gcc有多种语言前端,用于解析不同的语言。

4)gcc是按模块化设计的,可以加入新语言和新CPU架构的支持

5)gcc是自由软件

gcc编译过程

预处理(Pre-Processing)

编译(Compiling)

汇编(Assembling)

链接(Linking)

Gcc *.c –o 1exe (总的编译步骤)

Gcc –E 1.c –o 1.i  //宏定义 宏展开

Gcc –S 1.i –o 1.s

Gcc –c 1.s –o 1.o

Gcc 1.o –o 1exe

结论:gcc编译工具是一个工具链。。。。

            图:程序编译流程

解析:hello程序是一个高级C语言程序,这种形式容易被人读懂。为了在系统上运行hello.c程序,每条C语句都必须转化为低级机器指令。然后将这些指令打包成可执行目标文件格式,并以二进制形式存储器于磁盘中。

gcc常用编译选项

选项

作用

-o

产生目标(.i、.s、.o、可执行文件等)

-c

通知gcc取消链接步骤,即编译源码并在最后生成目标文件

-E

只运行C预编译器

-S

告诉编译器产生汇编语言文件后停止编译,产生的汇编语言文件扩展名为.s

-Wall

使gcc对源文件的代码有问题的地方发出警告

-Idir

将dir目录加入搜索头文件的目录路径

-Ldir

将dir目录加入搜索库的目录路径

-llib

链接lib库

-g

在目标文件中嵌入调试信息,以便gdb之类的调试程序调试

练习

gcc -E hello.c -o hello.i(预处理)

gcc -S hello.i -o hello.s(编译)

gcc -c hello.s -o hello.o(汇编)

gcc hello.o -o hello(链接)

以上四个步骤,可合成一个步骤

gcc hello.c -o hello(直接编译链接成可执行目标文件)

gcc -c hello.c或gcc -c hello.c -o hello.o(编译生成可重定位目标文件)

建议初学都加这个选项。下面这个例子如果不加-Wall选项编译器不报任何错误,但是得到的结果却不是预期的。

#include <stdio.h>

int main(void)

{

printf("2+1 is %f", 3);

return 0;

}

Gcc编译多个.c

hello_1.h

hello_1.c

main.c

一次性编译

gcc  hello_1.c main.c –o newhello

独立编译

gcc -Wall -c main.c -o main.o

gcc -Wall -c hello_1.c -o hello_fn.o

gcc -Wall main.o hello_1.o -o newhello

二、模板函数反汇编观察

命令:g++ -S 7.cpp -o 7.s

  1. .file "7.cpp"
  2. .text
  3. .def __ZL6printfPKcz; .scl 3; .type 32; .endef
  4. __ZL6printfPKcz:
  5. LFB264:
  6. .cfi_startproc
  7. pushl %ebp
  8. .cfi_def_cfa_offset 8
  9. .cfi_offset 5, -8
  10. movl %esp, %ebp
  11. .cfi_def_cfa_register 5
  12. pushl %ebx
  13. subl $36, %esp
  14. .cfi_offset 3, -12
  15. leal 12(%ebp), %eax
  16. movl %eax, -12(%ebp)
  17. movl -12(%ebp), %eax
  18. movl %eax, 4(%esp)
  19. movl 8(%ebp), %eax
  20. movl %eax, (%esp)
  21. call ___mingw_vprintf
  22. movl %eax, %ebx
  23. movl %ebx, %eax
  24. addl $36, %esp
  25. popl %ebx
  26. .cfi_restore 3
  27. popl %ebp
  28. .cfi_restore 5
  29. .cfi_def_cfa 4, 4
  30. ret
  31. .cfi_endproc
  32. LFE264:
  33. .lcomm __ZStL8__ioinit,1,1
  34. .def ___main; .scl 2; .type 32; .endef
  35. .section .rdata,"dr"
  36. LC0:
  37. .ascii "a:%d b:%d \12\0"
  38. LC1:
  39. .ascii "c1:%c c2:%c \12\0"
  40. LC2:
  41. .ascii "pause\0"
  42. .text
  43. .globl _main
  44. .def _main; .scl 2; .type 32; .endef
  45. _main:
  46. LFB1023:
  47. .cfi_startproc
  48. .cfi_personality 0,___gxx_personality_v0
  49. .cfi_lsda 0,LLSDA1023
  50. pushl %ebp
  51. .cfi_def_cfa_offset 8
  52. .cfi_offset 5, -8
  53. movl %esp, %ebp
  54. .cfi_def_cfa_register 5
  55. andl $-16, %esp
  56. subl $32, %esp
  57. call ___main
  58. movl $0, 28(%esp)
  59. movl $10, 24(%esp)
  60. movb $97, 23(%esp)
  61. movb $98, 22(%esp)
  62. leal 24(%esp), %eax
  63. movl %eax, 4(%esp)
  64. leal 28(%esp), %eax
  65. movl %eax, (%esp)
  66. call __Z6myswapIiEvRT_S1_ //66 ===>126
  67. movl 24(%esp), %edx
  68. movl 28(%esp), %eax
  69. movl %edx, 8(%esp)
  70. movl %eax, 4(%esp)
  71. movl $LC0, (%esp)
  72. call __ZL6printfPKcz
  73. leal 22(%esp), %eax
  74. movl %eax, 4(%esp)
  75. leal 23(%esp), %eax
  76. movl %eax, (%esp)
  77. call __Z6myswapIcEvRT_S1_ //77 ===>155
  78. movzbl 22(%esp), %eax
  79. movsbl %al, %edx
  80. movzbl 23(%esp), %eax
  81. movsbl %al, %eax
  82. movl %edx, 8(%esp)
  83. movl %eax, 4(%esp)
  84. movl $LC1, (%esp)
  85. call __ZL6printfPKcz
  86. movl $LC2, (%esp)
  87. LEHB0:
  88. call _system
  89. LEHE0:
  90. movl $0, %eax
  91. jmp L7
  92. L6:
  93. movl %eax, (%esp)
  94. LEHB1:
  95. call __Unwind_Resume
  96. LEHE1:
  97. L7:
  98. leave
  99. .cfi_restore 5
  100. .cfi_def_cfa 4, 4
  101. ret
  102. .cfi_endproc
  103. LFE1023:
  104. .def ___gxx_personality_v0; .scl 2; .type 32; .endef
  105. .section .gcc_except_table,"w"
  106. LLSDA1023:
  107. .byte 0xff
  108. .byte 0xff
  109. .byte 0x1
  110. .uleb128 LLSDACSE1023-LLSDACSB1023
  111. LLSDACSB1023:
  112. .uleb128 LEHB0-LFB1023
  113. .uleb128 LEHE0-LEHB0
  114. .uleb128 L6-LFB1023
  115. .uleb128 0
  116. .uleb128 LEHB1-LFB1023
  117. .uleb128 LEHE1-LEHB1
  118. .uleb128 0
  119. .uleb128 0
  120. LLSDACSE1023:
  121. .text
  122. .section .text$_Z6myswapIiEvRT_S1_,"x"
  123. .linkonce discard
  124. .globl __Z6myswapIiEvRT_S1_
  125. .def __Z6myswapIiEvRT_S1_; .scl 2; .type 32; .endef
  126. __Z6myswapIiEvRT_S1_: //126
  127. LFB1024:
  128. .cfi_startproc
  129. pushl %ebp
  130. .cfi_def_cfa_offset 8
  131. .cfi_offset 5, -8
  132. movl %esp, %ebp
  133. .cfi_def_cfa_register 5
  134. subl $16, %esp
  135. movl 8(%ebp), %eax
  136. movl (%eax), %eax
  137. movl %eax, -4(%ebp)
  138. movl 12(%ebp), %eax
  139. movl (%eax), %edx
  140. movl 8(%ebp), %eax
  141. movl %edx, (%eax)
  142. movl 12(%ebp), %eax
  143. movl -4(%ebp), %edx
  144. movl %edx, (%eax)
  145. leave
  146. .cfi_restore 5
  147. .cfi_def_cfa 4, 4
  148. ret
  149. .cfi_endproc
  150. LFE1024:
  151. .section .text$_Z6myswapIcEvRT_S1_,"x"
  152. .linkonce discard
  153. .globl __Z6myswapIcEvRT_S1_
  154. .def __Z6myswapIcEvRT_S1_; .scl 2; .type 32; .endef
  155. __Z6myswapIcEvRT_S1_: //155
  156. LFB1025:
  157. .cfi_startproc
  158. pushl %ebp
  159. .cfi_def_cfa_offset 8
  160. .cfi_offset 5, -8
  161. movl %esp, %ebp
  162. .cfi_def_cfa_register 5
  163. subl $16, %esp
  164. movl 8(%ebp), %eax
  165. movzbl (%eax), %eax
  166. movb %al, -1(%ebp)
  167. movl 12(%ebp), %eax
  168. movzbl (%eax), %edx
  169. movl 8(%ebp), %eax
  170. movb %dl, (%eax)
  171. movl 12(%ebp), %eax
  172. movzbl -1(%ebp), %edx
  173. movb %dl, (%eax)
  174. leave
  175. .cfi_restore 5
  176. .cfi_def_cfa 4, 4
  177. ret
  178. .cfi_endproc
  179. LFE1025:
  180. .text
  181. .def ___tcf_0; .scl 3; .type 32; .endef
  182. ___tcf_0:
  183. LFB1027:
  184. .cfi_startproc
  185. pushl %ebp
  186. .cfi_def_cfa_offset 8
  187. .cfi_offset 5, -8
  188. movl %esp, %ebp
  189. .cfi_def_cfa_register 5
  190. subl $8, %esp
  191. movl $__ZStL8__ioinit, %ecx
  192. call __ZNSt8ios_base4InitD1Ev
  193. leave
  194. .cfi_restore 5
  195. .cfi_def_cfa 4, 4
  196. ret
  197. .cfi_endproc
  198. LFE1027:
  199. .def __Z41__static_initialization_and_destruction_0ii; .scl 3; .type 32; .endef
  200. __Z41__static_initialization_and_destruction_0ii:
  201. LFB1026:
  202. .cfi_startproc
  203. pushl %ebp
  204. .cfi_def_cfa_offset 8
  205. .cfi_offset 5, -8
  206. movl %esp, %ebp
  207. .cfi_def_cfa_register 5
  208. subl $24, %esp
  209. cmpl $1, 8(%ebp)
  210. jne L11
  211. cmpl $65535, 12(%ebp)
  212. jne L11
  213. movl $__ZStL8__ioinit, %ecx
  214. call __ZNSt8ios_base4InitC1Ev
  215. movl $___tcf_0, (%esp)
  216. call _atexit
  217. L11:
  218. leave
  219. .cfi_restore 5
  220. .cfi_def_cfa 4, 4
  221. ret
  222. .cfi_endproc
  223. LFE1026:
  224. .def __GLOBAL__sub_I_main; .scl 3; .type 32; .endef
  225. __GLOBAL__sub_I_main:
  226. LFB1028:
  227. .cfi_startproc
  228. pushl %ebp
  229. .cfi_def_cfa_offset 8
  230. .cfi_offset 5, -8
  231. movl %esp, %ebp
  232. .cfi_def_cfa_register 5
  233. subl $24, %esp
  234. movl $65535, 4(%esp)
  235. movl $1, (%esp)
  236. call __Z41__static_initialization_and_destruction_0ii
  237. leave
  238. .cfi_restore 5
  239. .cfi_def_cfa 4, 4
  240. ret
  241. .cfi_endproc
  242. LFE1028:
  243. .section .ctors,"w"
  244. .align 4
  245. .long __GLOBAL__sub_I_main
  246. .ident "GCC: (rev2, Built by MinGW-builds project) 4.8.0"
  247. .def ___mingw_vprintf; .scl 2; .type 32; .endef
  248. .def _system; .scl 2; .type 32; .endef
  249. .def __Unwind_Resume; .scl 2; .type 32; .endef
  250. .def __ZNSt8ios_base4InitD1Ev; .scl 2; .type 32; .endef
  251. .def __ZNSt8ios_base4InitC1Ev; .scl 2; .type 32; .endef
  252. .def _atexit; .scl 2; .type 32; .endef

  

函数模板机制结论

1.编译器并不是把函数模板处理成能够处理任意类的函数

2.编译器从函数模板通过具体类型产生不同的函数

3.编译器会对函数模板进行两次编译。在声明的地方对模板代码本身进行编译;在调用的地方对参数替换后的代码进行编译。

C++编译器模板机制剖析的更多相关文章

  1. C++编译器函数模版机制剖析 - 函数模版的本质

    思考:为什么函数模板能够和函数重载放在一块.C++编译器是怎样提供函数模板机制的? demo 1 #include <cstdio> #include <iostream> u ...

  2. WPF源代码分析系列一:剖析WPF模板机制的内部实现(一)

    众所周知,在WPF框架中,Visual类是可以提供渲染(render)支持的最顶层的类,所有可视化元素(包括UIElement.FrameworkElment.Control等)都直接或间接继承自Vi ...

  3. C#进阶系列——WebApi 路由机制剖析:你准备好了吗?

    前言:从MVC到WebApi,路由机制一直是伴随着这些技术的一个重要组成部分. 它可以很简单:如果你仅仅只需要会用一些简单的路由,如/Home/Index,那么你只需要配置一个默认路由就能简单搞定: ...

  4. 【C#】 WebApi 路由机制剖析

    C#进阶系列——WebApi 路由机制剖析:你准备好了吗? 转自:https://blog.csdn.net/wulex/article/details/71601478 2017年05月11日 10 ...

  5. C#进阶系列——WebApi 路由机制剖析:你准备好了吗? 转载https://www.cnblogs.com/landeanfen/p/5501490.html

    阅读目录 一.MVC和WebApi路由机制比较 1.MVC里面的路由 2.WebApi里面的路由 二.WebApi路由基础 1.默认路由 2.自定义路由 3.路由原理 三.WebApi路由过程 1.根 ...

  6. WebApi 路由机制剖析

    阅读目录 一.MVC和WebApi路由机制比较 1.MVC里面的路由 2.WebApi里面的路由 二.WebApi路由基础 1.默认路由 2.自定义路由 3.路由原理 三.WebApi路由过程 1.根 ...

  7. ectouch第七讲 之ECshop模板机制整理

    网上的资源感觉还是有些用,可以看看,帮助理解,ECshop模板机制整理原文:http://blog.sina.com.cn/s/blog_6900af430100nkn8.html 一.模板引擎: E ...

  8. ECshop模板机制

    ECshop模板机制整理 模板机制 近期新项目涉及到ECshop的二次开发,趁此良机正好可以对闻名已久的ECshop系统进行深入了解.要了解一个系统,那么该系统的模板机制就是最重要的一环.相关整理如下 ...

  9. Java反射机制剖析(四)-深度剖析动态代理原理及总结

    动态代理类原理(示例代码参见java反射机制剖析(三)) a)  理解上面的动态代理示例流程 a)  理解上面的动态代理示例流程 b)  代理接口实现类源代码剖析 咱们一起来剖析一下代理实现类($Pr ...

随机推荐

  1. [图书] C++

    作者 书名 Bjarne Stroustrup    The Design and Evolution of C++Stanley B. Lippman    C++ PrimerStanley B. ...

  2. “找女神要QQ号码”——java篇

    题目就是这样的: 给了一串数字(不是QQ号码),根据下面规则可以找出QQ号码: 首先删除第一个数,紧接着将第二个数放到这串数字的末尾,再将第三个数删除,并将第四个数放到这串数字的末尾...... 如此 ...

  3. vim配置函数跳转(c/c++)

    暂时草记一下,有时间好好整理 ctags 如果只是查看函数与变量是在哪里定义的,用ctags就可以了. ctrl+]跳到定义的地方,ctrl+t跳回来. 想要像IDE那样在旁边显示函数与变量列表,用t ...

  4. ubuntu部署nginx

    先更新本机内置的程序. sudo apt-get updatesudo apt-get upgrade再判断系统是否内置了add-apt-repository命令,如果没有执行下列命令安装 sudo ...

  5. eclipse+gnuarm+使用报错

    Description Resource Path Location TypeProgram "echo" not found in PATH stm32 Project Prop ...

  6. PAT天梯赛L2-003 月饼【贪心】

    L2-003. 月饼 时间限制 100 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 陈越 月饼是中国人在中秋佳节时吃的一种传统食品,不同地区有许多不 ...

  7. 微信都在用的移动敏捷测试方法和工具|视频+PPT

    本文是腾讯优测总监雷彬在MPD2016 北京站上的演讲视频.他详细讲述了腾讯多年来在实践敏捷研发过程中测试的优化之路,为测试角色(包括测试工程师和开发自测)提供敏捷作业的思路.点击此处观看视频.时长5 ...

  8. Oracle中的时间函数用法(to_date、to_char) (总结)

    一.24小时的形式显示出来要用HH24 select to_char(sysdate,'yyyy-MM-dd HH24:mi:ss') from dual; select to_date('2005- ...

  9. 冒泡排序之python

    冒泡排序(Bubble sort) 两两比较相邻记录的关键字,如果反序则交换,直到没有反序记录为止. 1.算法描述: 比较相邻的元素.如果第一个比第二个大,就交换它们两个: 对每一对相邻元素作同样的工 ...

  10. 《前端JavaScript面试技巧》笔记一

    思考: 拿到一个面试题,你第一时间看到的是什么 -> 考点 又如何看待网上搜出来的永远也看不完的题海 -> 不变应万变 如何对待接下来遇到的面试题 -> 题目到知识再到题目 知识体系 ...