字符串作为指针与数组

时间:2013-06-11 18:38:48

标签: c++ arrays string pointers const

我想知道以下定义之间存在什么差异:

// file.cpp:
namespace n
{
static char const * const str1 = "hello";
static char const str2[] = "hello";
}

我想要的行为,我认为他们都提供:

  • 它们都引用不可变数据(因为数据是char consts)
  • 两个变量都不能修改(因为str1被定义为* const,因为str2是一个数组,不能用作l值?)
  • 他们都有内部联系(通过静态)
  • 他们都有命名空间范围
  • 如果指向任一字符串数据的指针可用于其他模块(通过此处未指定的某些函数),则这些字符串的内存将有效(str1因为它指向字符串文字,而str2因为数组是在命名空间范围内声明)

该语言是否有任何差异? 如果存在依赖于实现的行为,我如何调查不同平台上的差异?

(对于这个例子,我对将这些行为与std :: string选项进行对比不感兴趣,但是如果你认为其他读者会感兴趣,也可以随意谈论它。)

3 个答案:

答案 0 :(得分:5)

是的,有:一个仍然是数组,另一个是指针。指针和数组不一样。

一个特定的方面可能是使用sizeof运算符 - 对于指针,它不会导致字符串的长度,它将在数组上(终止的NUL字符也计入,当然)。

答案 1 :(得分:4)

你可以很容易地遇到两者之间的差异,因为一个是数组而另一个是指针。例如,sizeof将评估n::str1n::str2的不同(即不相关)值。另外,它们都是左值(是什么让你觉得它们不是?),这意味着你可以对它们应用&并获得完全不同的结果

&n::str1; // evaluates to a `char const *const *` value
&n::str2; // evaluates to a `char const (*)[6]` value

另请注意,第一个是指向一些不可变实现拥有的“字符串文字存储区”的直接指针,而第二个是由“you”拥有的数组,通过复制上述“字符串”中的数据进行初始化字面存储区“。允许实现在整个程序中合并这些实现拥有的字符串文字。例如,您声明使用相同的字符串文字

初始化另一个指针
char const *str_another = "hello";

语言保证str_another不指向n::str2

assert(str_another != n::str2); // will not fail

但它并不能保证str_anothern::str1

不同
assert(str_another != n::str1); // can fail

答案 2 :(得分:1)

&n::str1char const * const *,但&n::str2char const (*)[6]

您可以在函数重载分辨率方面获得一些差异,但可能仅在其中一个重载使用引用数组类型时才会出现。

template<typename T>
void f(T); // #1

template<typename T, std::size_t N>
void f(T (&)[N]); // #2

void g() {
    f(n::str1); // calls #1, T is char const*
    f(n::str2); // calls #2, T is char const, N is 6.
}

此外,正如@ H2CO3指出的那样,sizeof(n::str1)sizeof(char const*),但sizeof(n::str2)为6。