user-0 提问: 《深入理解计算机系统》里的链接器部分问题

回复:
user: user-0
content: 引用 12 楼 fetag 的回复:变量在使用之前，会有 “定义” 和 “初始化” 两个操作。其中“定义”的部分是告诉编译器 后面遇到这个标识符要怎样对待，在这个  步骤的时候，编译器是不会实际分配内存空间的；而初始化部分，就是要确实分配内存了，因为要首次给这个变量赋值了。  理解了上面的过程，就很容易解释 extern 关键字了。它的一个含义是：该变量已经在别处初始化过了，此处只是引用，相当于一  个定义，不用为其重新分配内存空间。  从编译器的角度看，foo3.c 和 bar3.c 中的两个x是完全不同的，因为一个初始化了，一个未初始化。未初始化的全局变量 是放在  可执行程序中.bss段的，它不会增加可执行程序的大小；而初始化了的全局变量 是放在.data段中的，这个会增加可执行程序的大  小。举个例子，假如那个x是个长度为100的数组，则初始化了和未初始化的，会导致编译完成的可执行程序size相差大概99左右。 谢谢！！

user: user-0
content: 引用 13 楼 u012033027 的回复:各位洋洋洒洒很多文字，跟楼主的问题几乎不沾边。 楼主的问题，书中已经解释了。初始化的变量是强符号，未初始化的变量是弱符号。所以bar3.c中定义了一个x，但是与foo3.c中的另一个x定义冲突，所以使用了foo3.c中的定义（因为这里是强定义）。 至于为什么没有extern，应该是因为bar2.c中关于x的定义就说明了它要有一个x，但是被foo3.c中的替换了，所以就不用extern定义了。 谢谢！！

user: user-1
content: 引用 9 楼 sunranlb 的回复:那这么说来extend关键字又有什么用呢？这样重名的变量岂不是都可以不用extend关键字了？ int x;编译器会给全局变量分配空间。extend int x; extend其实就是说我编译器不会为这个x分配空间，链接成可执行文件的时候 你链接器要在其他o文件里找。

user: user-2
content: 各位洋洋洒洒很多文字，跟楼主的问题几乎不沾边。 楼主的问题，书中已经解释了。初始化的变量是强符号，未初始化的变量是弱符号。所以bar3.c中定义了一个x，但是与foo3.c中的另一个x定义冲突，所以使用了foo3.c中的定义（因为这里是强定义）。 至于为什么没有extern，应该是因为bar2.c中关于x的定义就说明了它要有一个x，但是被foo3.c中的替换了，所以就不用extern定义了。

user: user-3
content: 变量在使用之前，会有 “定义” 和 “初始化” 两个操作。其中“定义”的部分是告诉编译器 后面遇到这个标识符要怎样对待，在这个  步骤的时候，编译器是不会实际分配内存空间的；而初始化部分，就是要确实分配内存了，因为要首次给这个变量赋值了。  理解了上面的过程，就很容易解释 extern 关键字了。它的一个含义是：该变量已经在别处初始化过了，此处只是引用，相当于一  个定义，不用为其重新分配内存空间。  从编译器的角度看，foo3.c 和 bar3.c 中的两个x是完全不同的，因为一个初始化了，一个未初始化。未初始化的全局变量 是放在  可执行程序中.bss段的，它不会增加可执行程序的大小；而初始化了的全局变量 是放在.data段中的，这个会增加可执行程序的大  小。举个例子，假如那个x是个长度为100的数组，则初始化了和未初始化的，会导致编译完成的可执行程序size相差大概99左右。

user: user-4
content: 引用 9 楼 sunranlb 的回复:[quote=引用 2 楼 ypzhong 的回复:] [quote=引用 1 楼 zhao4zhong1 的回复:] 有工夫阅读一下Linux下链接器的源代码。 别出馊主意了，这种问题读源码比直接看理论难多少倍。 楼主多看几遍原文，你看第一行的意思，如果一个模块里x未被初始化，那么链接器会选择另外一个被初始化的x。明显foo3.c这个模块x被初始化了，那么链接器会把 bar3.c f()函数里的x链接到foo3.c里的x。链接不仅仅是很多个o文件的函数链接到同一个可执行文件里，还包括全局变量。[/quote]  那这么说来extend关键字又有什么用呢？这样重名的变量岂不是都可以不用extend关键字了？  PS：谢谢老师的回答，你的回答比1楼强多了！[/quote]  读书时一个层次； 读源码是一个层次； 写源码是一个层析

user: user-0
content: 引用 2 楼 ypzhong 的回复:[quote=引用 1 楼 zhao4zhong1 的回复:] 有工夫阅读一下Linux下链接器的源代码。 别出馊主意了，这种问题读源码比直接看理论难多少倍。 楼主多看几遍原文，你看第一行的意思，如果一个模块里x未被初始化，那么链接器会选择另外一个被初始化的x。明显foo3.c这个模块x被初始化了，那么链接器会把 bar3.c f()函数里的x链接到foo3.c里的x。链接不仅仅是很多个o文件的函数链接到同一个可执行文件里，还包括全局变量。[/quote]  那这么说来extend关键字又有什么用呢？这样重名的变量岂不是都可以不用extend关键字了？  PS：谢谢老师的回答，你的回答比1楼强多了！

user: user-5
content: 吓我一跳， 还好VS中.obj符号名重复会报警

user: user-6
content: 引用 2 楼 ypzhong 的回复:[quote=引用 1 楼 zhao4zhong1 的回复:] 有工夫阅读一下Linux下链接器的源代码。 别出馊主意了，这种问题读源码比直接看理论难多少倍。 楼主多看几遍原文，你看第一行的意思，如果一个模块里x未被初始化，那么链接器会选择另外一个被初始化的x。明显foo3.c这个模块x被初始化了，那么链接器会把 bar3.c f()函数里的x链接到foo3.c里的x。链接不仅仅是很多个o文件的函数链接到同一个可执行文件里，还包括全局变量。[/quote] 很多情况下，使用最笨最累最痛苦的办法学习一门技术，比使用最聪明最轻松最舒服的办法学习这门技术学得更到位且体会更刻骨铭心。

user: user-1
content: 引用 1 楼 zhao4zhong1 的回复:有工夫阅读一下Linux下链接器的源代码。 别出馊主意了，这种问题读源码比直接看理论难多少倍。 楼主多看几遍原文，你看第一行的意思，如果一个模块里x未被初始化，那么链接器会选择另外一个被初始化的x。明显foo3.c这个模块x被初始化了，那么链接器会把 bar3.c f()函数里的x链接到foo3.c里的x。链接不仅仅是很多个o文件的函数链接到同一个可执行文件里，还包括全局变量。

user: user-6
content: 引用 7 楼 ypzhong 的回复:[quote=引用 6 楼 zhao4zhong1 的回复:] [quote=引用 5 楼 ypzhong 的回复:] [quote=引用 3 楼 zhao4zhong1 的回复:] [quote=引用 2 楼 ypzhong 的回复:] [quote=引用 1 楼 zhao4zhong1 的回复:] 有工夫阅读一下Linux下链接器的源代码。 别出馊主意了，这种问题读源码比直接看理论难多少倍。 楼主多看几遍原文，你看第一行的意思，如果一个模块里x未被初始化，那么链接器会选择另外一个被初始化的x。明显foo3.c这个模块x被初始化了，那么链接器会把 bar3.c f()函数里的x链接到foo3.c里的x。链接不仅仅是很多个o文件的函数链接到同一个可执行文件里，还包括全局变量。[/quote] 很多情况下，使用最笨最累最痛苦的办法学习一门技术，比使用最聪明最轻松最舒服的办法学习这门技术学得更到位且体会更刻骨铭心。[/quote] 不要很多情况，就在这个情况下你来说说你看到源码体会和直接给你原理的体会有什么不一样。[/quote] 源码实现时遇到的N多特殊情况以及在该情况下如何做，在原理、书籍、博客、讲演稿、……中没提的多了。  说是一物即不中。  不要迷信书、考题、老师、回帖； 要迷信CPU、编译器、调试器、运行结果。 并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。 任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实！  有人说一套做一套，你相信他说的还是相信他做的？ 其实严格来说这个世界上古往今来所有人都是说一套做一套，不是吗？ [/quote] 你不去创办个宗教就可惜了，绝对这方面的人才，因为你们有一个共同点，就是一个答案解释所有问题。[/quote] 实践是检验真理的唯一标准。

user: user-1
content: 引用 6 楼 zhao4zhong1 的回复:[quote=引用 5 楼 ypzhong 的回复:] [quote=引用 3 楼 zhao4zhong1 的回复:] [quote=引用 2 楼 ypzhong 的回复:] [quote=引用 1 楼 zhao4zhong1 的回复:] 有工夫阅读一下Linux下链接器的源代码。 别出馊主意了，这种问题读源码比直接看理论难多少倍。 楼主多看几遍原文，你看第一行的意思，如果一个模块里x未被初始化，那么链接器会选择另外一个被初始化的x。明显foo3.c这个模块x被初始化了，那么链接器会把 bar3.c f()函数里的x链接到foo3.c里的x。链接不仅仅是很多个o文件的函数链接到同一个可执行文件里，还包括全局变量。[/quote] 很多情况下，使用最笨最累最痛苦的办法学习一门技术，比使用最聪明最轻松最舒服的办法学习这门技术学得更到位且体会更刻骨铭心。[/quote] 不要很多情况，就在这个情况下你来说说你看到源码体会和直接给你原理的体会有什么不一样。[/quote] 源码实现时遇到的N多特殊情况以及在该情况下如何做，在原理、书籍、博客、讲演稿、……中没提的多了。  说是一物即不中。  不要迷信书、考题、老师、回帖； 要迷信CPU、编译器、调试器、运行结果。 并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。 任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实！  有人说一套做一套，你相信他说的还是相信他做的？ 其实严格来说这个世界上古往今来所有人都是说一套做一套，不是吗？ [/quote] 你不去创办个宗教就可惜了，绝对这方面的人才，因为你们有一个共同点，就是一个答案解释所有问题。

user: user-6
content: 引用 5 楼 ypzhong 的回复:[quote=引用 3 楼 zhao4zhong1 的回复:] [quote=引用 2 楼 ypzhong 的回复:] [quote=引用 1 楼 zhao4zhong1 的回复:] 有工夫阅读一下Linux下链接器的源代码。 别出馊主意了，这种问题读源码比直接看理论难多少倍。 楼主多看几遍原文，你看第一行的意思，如果一个模块里x未被初始化，那么链接器会选择另外一个被初始化的x。明显foo3.c这个模块x被初始化了，那么链接器会把 bar3.c f()函数里的x链接到foo3.c里的x。链接不仅仅是很多个o文件的函数链接到同一个可执行文件里，还包括全局变量。[/quote] 很多情况下，使用最笨最累最痛苦的办法学习一门技术，比使用最聪明最轻松最舒服的办法学习这门技术学得更到位且体会更刻骨铭心。[/quote] 不要很多情况，就在这个情况下你来说说你看到源码体会和直接给你原理的体会有什么不一样。[/quote] 源码实现时遇到的N多特殊情况以及在该情况下如何做，在原理、书籍、博客、讲演稿、……中没提的多了。  说是一物即不中。  不要迷信书、考题、老师、回帖； 要迷信CPU、编译器、调试器、运行结果。 并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。 任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实！  有人说一套做一套，你相信他说的还是相信他做的？ 其实严格来说这个世界上古往今来所有人都是说一套做一套，不是吗？

user: user-1
content: 引用 3 楼 zhao4zhong1 的回复:[quote=引用 2 楼 ypzhong 的回复:] [quote=引用 1 楼 zhao4zhong1 的回复:] 有工夫阅读一下Linux下链接器的源代码。 别出馊主意了，这种问题读源码比直接看理论难多少倍。 楼主多看几遍原文，你看第一行的意思，如果一个模块里x未被初始化，那么链接器会选择另外一个被初始化的x。明显foo3.c这个模块x被初始化了，那么链接器会把 bar3.c f()函数里的x链接到foo3.c里的x。链接不仅仅是很多个o文件的函数链接到同一个可执行文件里，还包括全局变量。[/quote] 很多情况下，使用最笨最累最痛苦的办法学习一门技术，比使用最聪明最轻松最舒服的办法学习这门技术学得更到位且体会更刻骨铭心。[/quote] 不要很多情况，就在这个情况下你来说说你看到源码体会和直接给你原理的体会有什么不一样。

user: user-6
content: 有工夫阅读一下Linux下链接器的源代码。