为什么在多重定义的情况下char *和char []之间存在差异?

时间:2013-04-22 09:08:08

标签: c++ arrays memory-management global-variables multiple-definition-error

  • 在interface.h中定义strInterface

    // interface.h
    #ifndef INTERFACE_H_
    #define INTERFACE_H_
    const char* strInterface = "the difference between char* and char array";
    #endif
    
  • 在OneUsing类中,
  • 调用strInterface字符串

    // oneUsingInterface.h
    #ifndef ONEUSINGINTERFACE_H_
    #define ONEUSINGINTERFACE_H_
    
    class OneUsing
    {
    private:
        int mData;
    public:
        OneUsing();
        OneUsing(int a);
        void print();
    };
    #endif  // ONEUSINGINTERFACE_H_
    
    // oneUsingInterface.cpp
    #include "oneUsingInterface.h"
    #include "interface.h"
    #include <iostream>
    
    using namespace std;
    
    OneUsing::OneUsing()
    {}
    OneUsing::OneUsing(int a)
    {
        mData = a;
    }
    void OneUsing::print()
    {
        cout<<"mData: "<<mData<<" strInterface: "<<strInterface<<endl;
    
    }
    
  • 在main.cpp中,
  • 包含了interface.h,因为strInterface是直接调用的;它还包括oneUsingInterface.h,因为将创建OneUsing实例。

    //main.cpp
    #include <iostream>
    #include "interface.h"
    #include "oneUsingInterface.h"
    
    using namespace std;
    
    int main()
    {
        cout<<strInterface<<endl;
        OneUsing* pObject = new OneUsing(5);
        pObject->print();
    }
    
  • 现在,问题出现了:

    g++ -I../boost_1_52_0/installation/prefix/include -I../boost_1_52_0/installation/prefix/lib -g -Wall -Wextra -c .//main.cpp
    g++ -I../boost_1_52_0/installation/prefix/include -I../boost_1_52_0/installation/prefix/lib -g -Wall -Wextra -c .//oneUsingInterface.cpp
    g++ -I../boost_1_52_0/installation/prefix/include -I../boost_1_52_0/installation/prefix/lib -g -Wall -Wextra main.o oneUsingInterface.o -o main
    oneUsingInterface.o:(.data+0x0): multiple definition of `strInterface'
    main.o:(.data+0x0): first defined here
    collect2: error: ld returned 1 exit status
    make: *** [main] Error 1
    
  • 但是,如果strInterface是这样定义的,那么就没问题了:

    // interface.h
    #ifndef INTERFACE_H_
    #define INTERFACE_H_
    const char strInterface[] = "the difference between char* and char array";
    #endif
    

在这种情况下,有些人可以告诉我有关char*char[]之间差异的详细信息吗?

PS:我们经常在头文件中用extern关键字声明全局变量,并在某人的实现文件中定义它。

3 个答案:

答案 0 :(得分:2)

不同之处在于const char strInterface[]定义了一个常量。常量对于它们包含的每个文件都是本地的。您将在每个文件中获得一个单独的副本。

指针const char* strInterface指向常量数据,但指针本身不是常量。因此,默认情况下,其他翻译单元可以看到它。

答案 1 :(得分:1)

声明为const的命名空间范围变量默认情况下具有内部链接,因此您可以在多个翻译单元中定义具有相同名称的变量,而不会导致链接错误。

此变量不是const,因此它将具有外部链接,这意味着任何程序中只能存在一个此类定义:

const char* strInterface = "...";

const版本将是:

const char* const strInterface = "...";

这是const,因为数组的constness与其元素的constness没有区别。 (IIRC在标准中对这一事实有一些正式的含糊不清。)你可以在一个程序中为每个翻译单元设置一个这样的定义。

const char strInterface[] = "...";

答案 2 :(得分:1)

这里有两种不同的类型:

首先,const char* strInterface是一个指向常量字符的指针,因此您在两个不同的编译单元中创建一个在全局范围内具有相同名称的指针,使链接器抱怨它。请注意,您可以使指针指向代码中稍后完全不同的内容。指针本身是可变的;它指向的字符串是不可变的。

其次,const char strInterface[]是一个常量字符数组,它是为每个编译单元本地创建的,因此链接器会找到该字符串的多个不会发生冲突的定义。这个常数是不可变的。