我正在做一些字符串操作并遇到问题。
char *arr1 = "HELLO";
(*arr1)++;
这会引发错误“访问违规写入位置”!
但是,下面的代码工作正常。
char arr1[] = "HELLO";
(*arr1)++;
什么是存储char * arr1和char arr1 []的内存段?
答案 0 :(得分:2)
char *arr1 = "HELLO";
上面的定义意味着arr1
的内存可以分配在内存的只读部分(实际上是实现定义的行为),因此可能导致'当您尝试更改内存位置的值时,“访问冲突”指向。
char arr1[] = "HELLO";
在这种情况下,arr1
的内存在堆栈中分配 - 这是可写的。因此,表达式(*arr1)++
可以正常运行。
答案 1 :(得分:0)
文字喜欢" HELLO"属于const char[]
的类型衰减到const char*
,编译器可以将它放在实际上无法修改的内存中,修改会导致未定义的行为。 g ++给出了如下警告:
main.cpp:7:14: warning: deprecated conversion from string constant to 'char*' [-Wwrite-strings]
char *arr1 = "HELLO";
编译器允许这样做,因为你可以在这里阅读(http://en.cppreference.com/w/cpp/language/string_literal):
在C中,字符串文字的类型为char [],可以直接赋值 到(非常)char *。 C ++ 03也允许它(但不赞成使用它, 因为文字是C ++中的const)。 C ++ 11不再允许这样的分配 没有演员。
但实际上即使启用了C ++ 11,我也不会在g ++上出错。
数组当然可以修改,所以你的第二个例子工作正常。这段代码:
char arr1[] = "HELLO";
在堆栈上创建一个长度为6的数组,并使用" HELLO \ 0"进行初始化。
答案 2 :(得分:0)
在第一种情况下,arr1
是一个局部变量,它保存一个指向包含字符串"HELLO"
的只读内存段的指针。语句(*arr1)++
尝试修改段的第一个字节(包含字符'H'
),这会导致访问冲突。
在第二种情况下,arr1
是一个局部变量,它包含一个由六个字节组成的数组,用{'H', 'E', 'L', 'L', 'O', 0}
初始化。局部变量在读写存储器中,因此修改它们不会导致错误。
答案 3 :(得分:0)
没有指针算术。您正在为字符串的第一个字符添加一个。由于字符串常量不可写,因此第一个版本会出错。在第二个版本中,您更改了on char数组的内容,因此没有问题。
答案 4 :(得分:0)
您没有执行任何指针算法。你取消引用指针然后递增它指向的东西(第一个字符)。
不幸的是,无法修改字符串文字(并且您的编译器应该警告char*
是坏的并且const char*
是好的,指向字符串文字)。
它适用于第二种情况,因为从字符串文字初始化本地数组会创建您自己的数据副本。