查询指针解引用

Query on Pointer dereferencing

本文关键字:引用 指针 查询      更新时间:2023-10-16

我正在做一些字符串操作,遇到了一个问题。

 char *arr1 = "HELLO";
 (*arr1)++;

this抛出错误"写location违反访问规则"!

但是,下面的代码可以正常工作。
 char arr1[] = "HELLO";
 (*arr1)++;

和char* arr1和char arr1[]存储在哪些内存段上?

 char *arr1 = "HELLO";

以上定义意味着arr1 的内存可以分配在内存的只读部分(实际上是实现定义的行为),因此当您试图更改内存位置指向的值时,可能会导致"访问冲突"。

char arr1[] = "HELLO";

在这种情况下,arr1的内存是在堆栈中分配的——堆栈是可写的。因此,表达式(*arr1)++工作正常,没有任何问题。

在第一种情况下,arr1是一个局部变量,它持有一个指针,指向包含字符串"HELLO"的只读内存段。语句(*arr1)++试图修改段(包含字符'H')的第一个字节,这会导致访问冲突。

在第二种情况下,arr1是一个局部变量,它包含一个6字节的数组,用{'H', 'E', 'L', 'L', 'O', 0}初始化。局部变量位于读写内存中,因此修改它们不会导致错误。

没有指针运算。您正在向字符串的第一个字符添加1。由于字符串常量不可写,第一个版本给出了一个错误。在第二个版本中,您更改了一个字符数组的内容,因此没有问题。

您没有做任何指针运算。您对指针解引用,然后对它所指向的对象(第一个字符)加1。

不幸的是,字符串字面值不能被修改(编译器应该警告你,对于指向字符串字面值,char*是坏的,const char*是好的)。

它在第二种情况下工作,因为从字符串文本初始化本地数组会创建您自己的数据副本。

像"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[]类型,可以直接赋值转换为(非const) char*。c++ 03也允许这样做(但已弃用),as字面量在c++中是const)。c++ 11不再允许这样的赋值没有强制转换

,但实际上我没有得到错误的g++,即使启用了c++ 11。

数组当然可以修改,所以第二个示例工作得很好。这段代码:

char arr1[] = "HELLO";

在栈上创建一个长度为6的数组,并初始化为"HELLO"