【问题标题】:String as pointer vs array [duplicate]字符串作为指针与数组[重复]
【发布时间】:2013-06-07 17:32:34
【问题描述】:

我想知道以下定义之间有什么区别:

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

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

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

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

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

【问题讨论】:

  • 没有区别。
  • @TaylorFlores 没有区别吗?真的吗?
  • @TaylorFlores 是的!
  • 哦?对不起,也许我应该问这个问题
  • @TaylorFlores 请阅读我的回答...

标签: c++ arrays string pointers constants


【解决方案1】:

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

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

还要注意,第一个是指向某个不可变的实现拥有的“字符串字面量存储区”的直接指针,而第二个是“you”拥有的数组,它是通过从上述“string”中复制数据来初始化的文字存储区”。允许实现在整个程序中合并那些实现拥有的字符串文字。例如,你声明另一个用相同的字符串字面量初始化的指针

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

【讨论】:

  • 左值出现在 VC++2012 'n::str2 = n::str2;'产生“错误 C2106:'=':左操作数必须是左值”。我要强调的主要一点是 str1 或 str2 都不是可分配的。原因也很有趣,但可能是次要的。
  • @user2246255: n::str2 = n::str2 是一个不好的例子,因为它可能会因为数组类型衰减而失败。但无论如何,赋值需要 LHS 上的可修改左值。如果某些东西是不可赋值的,那并不意味着它不是左值。这可能意味着左值是不可修改的。 n::str2 是不可修改的左值。
【解决方案2】:

&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。

【讨论】:

    【解决方案3】:

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

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

    【讨论】:

      猜你喜欢
      • 2011-03-13
      • 1970-01-01
      • 1970-01-01
      • 2014-09-22
      • 2012-09-29
      • 1970-01-01
      • 2021-10-27
      相关资源
      最近更新 更多