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

Why are there differences between char* and char[] in case of multiple definition?

本文关键字:char 之间 存在 定义 为什么 情况下      更新时间:2023-10-16
  • 在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关键字声明全局变量,我们在某人的实现文件中定义它。

不同之处在于const char strInterface[]定义了一个常量。常量是包含在每个文件中的本地常量。每个文件中都会有一个单独的副本。

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

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

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

const char* strInterface = "...";

const版本为:

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

这是const,因为数组的常量和元素的常量之间没有区别。(IIRC在标准中对这一事实有一些形式上的歧义。(在一个程序中,每个翻译单元可以有一个这样的定义。

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

这里有两种不同的类型:

首先,const char* strInterface是一个指向常量字符的指针,因此您在两个不同的编译单元中的全局作用域中创建了一个同名指针,这让链接器对此表示不满。请注意,您可以在代码的后面使指针指向完全不同的东西。指针本身是可变的;它指向的字符串是不可变的。

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