static char * vs static char []内存访问

时间:2013-07-02 12:14:22

标签: c++

我正在将一些C代码编译为C ++,并且遇到了令我困惑的事情。考虑从LuaFileSystem获取的以下函数。

static const char *perm2string (unsigned short mode) {
  static char perms[10] = "---------";
  //static char* perms = "---------";
  int i;
  for (i=0;i<9;i++) perms[i]='-';
  if (mode  & _S_IREAD)
   { perms[0] = 'r'; perms[3] = 'r'; perms[6] = 'r'; }
  if (mode  & _S_IWRITE)
   { perms[1] = 'w'; perms[4] = 'w'; perms[7] = 'w'; }
  if (mode  & _S_IEXEC)
   { perms[2] = 'x'; perms[5] = 'x'; perms[8] = 'x'; }
  return perms;
}

此代码可以正常工作,但是如果我取消注释注释行,它就会崩溃。我已经使用调试器来解决这个问题,并且似乎在static char* perms时,字符串被放置在只读内存中,因此第一个循环将导致访问冲突,使用静态数组不会导致此类问题。我很好奇当字符串未被声明为const时为什么会发生这种情况。

6 个答案:

答案 0 :(得分:3)

没错。

字符串文字是不可变的"---------"是字符串文字。您的static char*指向该字符串文字。

不可变性在编译时并不是固有的强制执行,所以当你尝试写入文字时,你会得到未定义的行为。这可能会导致运行时崩溃。

  

[C++11: 2.14.5/12]:是否所有字符串文字都是不同的(即存储在非重叠对象中)是实现定义的。 尝试修改字符串文字的效果未定义。

C ++实际上要求此指针为static char const*,但有些编译器仅警告

但是,使用字符串文字初始化数组复制字符串。该阵列是您自己的,随心所欲。这就是为什么你可以在没有崩溃的情况下修改static char[10]

  

[C++11: 8.5.2/1]:一个char数组(无论是普通charsigned char还是unsigned char),char16_t数组,char32_t数组还是{ {1}}数组可以分别由窄字符文字wchar_t字符串文字,char16_t字符串文字或宽字符串文字初始化,或者由括在括号中的适当类型的字符串文字初始化。 字符串文字值的连续字符初始化数组的元素。

答案 1 :(得分:2)

撰写以下内容时:

const char *X = "...."

您在只读内存中有"....",而X指向它。事实上,X的类型应该是const char *,而不仅仅是char *

另一方面,当你写:

char X[] = "...."

这相当于:

char X[] = {'.', '.', '.', '.', '\0'}

这是一个数组初始值设定项。换句话说,X将是一个数组(不是指针),它将包含"...."的内容。由于它不是const,您可以毫无问题地进行更改。

答案 2 :(得分:2)

字符串文字是const char *。您不能在C ++或C中修改它们。

由于遗产原因,他们可以转换为char *,但这并不能使其合法修改。

答案 3 :(得分:1)

字符串文字存储在内存的只读部分中。任何修改字符串文字内容的尝试都会在大多数实现中调用Undefined Behavior和segmentation fault。 因此,如果您需要一个可修改的char数组,则将其声明为char perms[10]而不是char* perms

答案 4 :(得分:0)

这是正常的,与c ++无关(你将得到与C相同的结果)。 static char* perms = "---------";是const,因为"---------"是二进制文件的一部分(您可以使用objdump程序看到它)

答案 5 :(得分:0)

char* perms = "-----"创建一个指向字符串的指针,该字符串位于受保护的段中。试图写入它会导致崩溃。

char perms[] = "-----"在堆栈上创建一个字符数组,并用“-----”中的相关字符填充它。

这是一个不相等的数组和指针的例子。