声明带有指针的字符串文字比声明常量数组更有效吗?

时间:2017-01-29 10:51:10

标签: c pointers

如果我想存储一个常量字符串,

const char array[] = "Some string literal.";

C引物加书说

  

然后引用的字符串存储在作为可执行文件一部分的数据段中。只有在程序开始运行后才会分配数组的内存。那时,引用的字符串将被复制到数组中。

这是否意味着内存为字符串文字分配了两次?

另一方面,当用指针声明时,它只为指针变量留出存储空间并将字符串文字的地址存储到其中。

const char *pt = "Some string literal.";

这意味着只有一个字符串文字的副本,并且使用字符串文字声明指针比数组的内存效率更高?

2 个答案:

答案 0 :(得分:6)

在第一种情况下,字符串的数据存储在可执行文件中,并在加载程序后存储在内存中。所以它是“分配两次”但是在非常不同的存储介质(磁盘和内存)中。

然而,对于第二种情况也是如此。字符串文字需要在磁盘上的可执行文件中存储一次,在程序运行时需要存储在内存中。

不同之处在于实现细节,即在第一种情况下,内存中的字符串存储在堆栈或某些全局可修改数据存储器段中。在第二种情况下,字符串通常与代码一起存储。

因此,如果在第一种情况下只有一个字符串实例,则“内存效率”没有区别。

答案 1 :(得分:6)

答案取决于定义是出现在全球范围还是本地范围内。

  • 在全球范围内:

    • 第一个选项定义初始化常量数组。使用array[0]从中读取字节将导致代码从全局内存位置读取单个字节,通常是单个指令。

    • 第二个选项定义了一个可修改的指针,该指针被初始化为指向一个常量字符数组。使用array[0]从中读取字节将导致代码加载指针值并读取指针指向的元素,通常至少有2条指令。

    如果您不需要更改array引用的字符串,则最好使用第一个选项。

  • 在本地范围(自动存储)

    • 第一个选项定义用字符串初始化的数组。如果此数组不是常量并且在函数内部被修改,则生成的代码将与此基本类似:

      char array[sizeof "Some string literal."];
      memcpy(array, "Some string literal.", sizeof(array));
      

      但由于它被定义为const,编译可以优化代码并生成对array的引用,作为静态存储中字符串文字的引用。为避免可能的代码生成(如上所述),您可以在本地范围内使用此定义:

      static const char array[] = "Some string literal.";
      
    • 相反,第二个选项定义了一个初始化为指向字符串文字的本地指针,它本身很可能存储在静态存储中,例如数据段甚至代码段。如果函数使用array,则定义可以生成一个存储来初始化指针,或者根据函数内部的特定代码以及编译器的效率,或多或少的代码从中读取字符。

      < / LI>

在全球范围内,使用第一种方法似乎更有效。

在本地范围内,它在很大程度上取决于实际使用的代码和编译器,但定义static const char数组可能效率最高。