multiple definition of `xxxx`问题解决及其原理,multipledefinition


原文地址:https://blog.csdn.net/mantis_1984/article/details/53571758

                                        <link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/template/css/ck_htmledit_views-e2445db1a8.css">
                    <div class="htmledit_views">
            <p><span >&nbsp; &nbsp; 人有的时候就是这样,稍微知道点知识就觉着自己什么都会,就浮躁了,实际只是一瓶子不满半瓶子晃荡的状态,今天就写点基础的东西,也是当前遇到的,以前改改就过去了,没有深究其原因,今天就给它所清楚了,也算弥补以前的旧账。</span></p><p><span >&nbsp; &nbsp; 早上编译一段代码,出现了如下的错误:</span></p><p><span ><img src="https://img-blog.csdn.net/20161211095611387?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbWFudGlzXzE5ODQ=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" align="middle"><br></span></p><p><span >&nbsp; &nbsp;multiple definition of `xxxxx`错误出现了,MD是不是谁写代码没在.h文件加条件编译啊?仔细查看了代码发现确实加了条件编译。</span></p><p></p><div><span ><span ><em>#ifndef _TEST_H_</em></span></span></div><div><span ><span ><em>#define _TEST_H_</em></span></span></div><div><span ><span ><em>。。。</em></span></span></div><div><span ><span ><em>#endif</em></span></span></div><div><span ><br></span></div><div><span >&nbsp; &nbsp;不是这个问题。这个问题哪里引起的呢?重复定义的问题,在哪里出现的呢?</span></div><div><span ><br></span></div><div><div><span >&nbsp; &nbsp; 要解决这个问题先来看看变量的定义和声明的区别。</span></div><div><span ><span >&nbsp; &nbsp; 声明是向编译器介绍名字--标识符,它告诉编译器“这个函数或变量在某处可找到,它的模样象什么”。</span><span >而定义是说:“在这里建立变量”或“在这里建立函数”。它为名字分配存储空间。无论定义的是函数还是变量,编译器都要为它们在定义点分配存储空间。对于变量,编译器确定变量的大小,然后在内存中开辟空间来保存其数据,对于函数,编译器会生成代码,这些代码最终也要占用一定的内存。</span><span >总之就是:把建立空间的声明成为“定义”,把不需要建立存储空间的成为“声明”。</span></span></div><div><div><div><span >&nbsp; &nbsp; 查看代码,确实我在一个.h文件中定义了一个变量,而这个.h文件被多个文件包含,单独编译都没有问题,但是到链接的时候就出现问题了。</span></div><div><span ><br></span></div><div><span ><em>#ifndef _TEST_H_</em></span></div><div><span ><em>#define _TEST_H_</em></span></div><div><span ><em><br></em></span></div><div><span ><em>......</em></span></div><div><span ><em><br></em></span></div><div><span ><em>struct pdesc const cameractrl_params[] = {<br><span>  </span>{PT_STRI_, 0, &nbsp;1, OFFSET(cameractrl, homecmd), "homecmd", 32, 0, NULL, NULL},<br>&nbsp; &nbsp; {PT_STRI_, 0, &nbsp;1, OFFSET(cameractrl, zoomctrl), "zoomctrl", 32, 0, NULL, NULL},<br>&nbsp; &nbsp; {PT_STRI_, 0, &nbsp;1, OFFSET(cameractrl, focusctrl), "focusctrl", 32, 0, NULL, NULL},<br>&nbsp; &nbsp; {PT_STRI_, 0, &nbsp;1, OFFSET(cameractrl, aperturectrl), "aperturectrl", 32, 0, NULL, NULL},<br>&nbsp; &nbsp; {PT_NULL_, 0, &nbsp;0, 0, "", 0, 0, NULL, NULL} /* PT_NULL means tail of struct pdesc array */<br>};<br></em></span></div><div><span ><em><br></em></span></div><div><span ><em>......</em></span></div><div><span ><em><br></em></span></div><div><span ><em>#endif</em></span></div><div><span ><br></span></div><div><span >&nbsp; &nbsp; 一般在.h文件中定义一个变量声明时,在其他文件中只要包含了这个.h文件,编译的时候就会独立被编译器解释,然后每个.C文件会生成独立的标识符和符号表,所以上述代码在单独编译的时候并不会报错,语法是合法的。但是,最后在编译器链接的时候,就会将工程中所有的符号整合在一起,由于文件中有重复的变量,于是就会出现重复定义的错误,系统就是提示你“multiple definition of `xxx`”。</span></div><div><span ><span >&nbsp; 进一步解释,我们可以这样想象编译每一个C源文件时,相当于一条有管道包围的纵向水流,二者互不干扰。当链接时两条原本相互独立的水管横向流了,所有就出现了重复的元素。所以当进行链接时就会出现重复定义的标示符。重复定义的标示符在这里只是变量,函数不会。因为函数确实只在.c中定义了一次,多次声明是没有问题的,而变量确实出现了两次定义。两次重复的变量定义链接器就不知道该已那个地址作为变量的内存,所以报错。</span></span></div><div><span ><span >&nbsp;</span></span></div><div><span ><span >&nbsp; 怎么解决这个问题呢?</span></span></div><div><span ><span ><br></span></span></div><div><span ><span >&nbsp; 其实只需要将全局变量定义从.h文件中挪到.c文件里,然后在.h文件中用extern做外部声明即可。即在.c文件中声明变量,然后在头文件.h所有的变量声明前加上extern,注意在.h文件中就不要对变量进行初始化赋值了。然后其他需要使用全局变量的.c文件中包含.h文件即可。编译器会为.c生成目标文件,然后链接时,如果该.c文件使用了全局变量,链接器就会链接到此.c文件。其他文件需要使用此全局变量也是同样的方式,目的其实只有一个,就是使变量在内存中唯一化。</span></span></div><div><span ><span >&nbsp;</span></span></div><div><span ><span >&nbsp;例子,上面代码如此修改就对了:</span></span></div><div><span ><span ><br></span></span></div><div><span >在test.c中定义</span></div><div><span ><em>//test.c</em></span></div><div><span ><em>......</em></span></div><div><span ><em><br></em></span></div><div><span ><em><span >struct pdesc const cameractrl_params[] = {</span><br ><span >    </span><span >{PT_STRI_, 0, &nbsp;1, OFFSET(cameractrl, homecmd), "homecmd", 32, 0, NULL, NULL},</span><br ><span >&nbsp; &nbsp; {PT_STRI_, 0, &nbsp;1, OFFSET(cameractrl, zoomctrl), "zoomctrl", 32, 0, NULL, NULL},</span><br ><span >&nbsp; &nbsp; {PT_STRI_, 0, &nbsp;1, OFFSET(cameractrl, focusctrl), "focusctrl", 32, 0, NULL, NULL},</span><br ><span >&nbsp; &nbsp; {PT_STRI_, 0, &nbsp;1, OFFSET(cameractrl, aperturectrl), "aperturectrl", 32, 0, NULL, NULL},</span><br ><span >&nbsp; &nbsp; {PT_NULL_, 0, &nbsp;0, 0, "", 0, 0, NULL, NULL} /* PT_NULL means tail of struct pdesc array */</span><br ><span >};</span><br></em></span></div><div><span ><em><br></em></span></div><div><span ><em>......</em></span></div><div><span ><br></span></div><div><span >在test.h中定义</span></div><div><span ><br></span></div><div><span ><em>//test.h</em></span></div><div><span ></span><div><span ><em>#ifndef _TEST_H_</em></span></div><div><span ><em>#define _TEST_H_</em></span></div><div><span ><em><br></em></span></div><div><span ><em>......</em></span></div><div><span ><em><br></em></span></div><div><span ><em>extern struct pdesc const cameractrl_params[];<br></em></span></div><div><span ><em><br></em></span></div><div><span ><em>......</em></span></div><div><span ><em><br></em></span></div><div><span ><em>#endif</em></span></div><br></div><div><span ><span ><br></span></span></div><div><span >&nbsp; 这样,multiple definition of `xxxx`就搞明白了。</span></div><div><span ><br></span></div><div><span ><span ><br></span></span></div><div><span >done</span></div><div><span ><span ><br></span></span></div></div></div><span ><br></span></div><div><span ><br></span></div><p></p><p><span ><br></span></p><p><br></p>            </div>
            </div>

相关内容

    暂无相关文章