我正在尝试使用指针更改字符数组组件的值。但是我不能这样做。使用两种不同的方法char A[]
和char *A
声明数组之间有根本的区别吗?
我尝试使用A[0]
访问数组,并且可以正常工作。但是我无法更改数组组件的值。
{
char *A = "ab";
printf("%c\n", A[0]); //Works. I am able to access A[0]
A[0] = 'c'; //Segmentation fault. I am not able to edit A[0]
printf("%c\n", A[0]);
}
预期输出:
a
c
实际输出:
a
Segmentation fault
答案 0 :(得分:3)
区别在于char A[]
定义了一个数组,而char *
没有定义一个数组。
要记住的最重要的事情是数组不是指针。
在此声明中:
char *A = "ab";
字符串文字"ab"
创建一个类型为char[3]
的匿名数组对象(终结点'\0'
用2加1)。该声明创建了一个名为A
的指针,并将其初始化为指向该数组的初始字符。
由字符串文字创建的数组对象具有静态存储持续时间(这意味着它在程序的整个执行过程中都存在),并且不允许您对其进行修改。 (严格来说,尝试对其进行修改具有未定义的行为。)它实际上应该是const char[3]
而不是char[3]
,但是由于历史原因,它没有被定义为const
。您应该使用指向const
的指针来引用它:
const char *A = "ab";
,以便编译器将捕获任何修改数组的尝试。
在此声明中:
char A[] = "ab";
字符串文字具有相同的作用,但是数组对象A
用该数组内容的副本初始化。数组A
是可修改的,因为您没有使用const
定义它-并且因为它是您创建的数组对象,而不是由字符串文字隐式创建的,所以您可以对其进行修改。>
像A[0]
这样的数组索引表达式实际上需要一个指针作为其操作数(另一个为整数)。通常,该指针是数组表达式“衰减”到指针的结果,但也可以只是一个指针-只要该指针指向数组对象的元素即可。
C中的数组和指针之间的关系很复杂,并且那里存在许多错误信息。我建议阅读comp.lang.c FAQ的第6节。
您可以使用数组名称或指针来引用数组对象的元素。您遇到了只读数组对象的问题。例如:
#include <stdio.h>
int main(void) {
char array_object[] = "ab"; /* array_object is writable */
char *ptr = array_object; /* or &array_object[0] */
printf("array_object[0] = '%c'\n", array_object[0]);
printf("ptr[0] = '%c'\n", ptr[0]);
}
输出:
array_object[0] = 'a'
ptr[0] = 'a'
答案 1 :(得分:2)
字符串文字不打算被覆盖,请将其视为只读。覆盖字符串是未定义的行为,因此您的计算机选择了使程序崩溃。您可以使用数组来修改字符串。
char A[3] = "ab";
A[0] = 'c';
答案 2 :(得分:2)
像"ab"
这样的字符串文字被假定为是不可变的,就像其他任何文字一样(您不能更改1
或{{1 }}, 例如)。但是,与数字文字不同,字符串文字 require 需要某种形式的存储。有些实现(例如您正在使用的实现)显然将字符串文字存储在只读存储器中,因此尝试更改文字的内容将导致段错误。
语言定义使行为未定义-可能按预期运行,可能会完全崩溃,或者可能会执行其他操作。
答案 3 :(得分:1)
使用两种不同的方法
char A[]
和char *A
声明数组之间有根本区别吗?
是的,因为第二个不是数组而是指针。
"ab"
的类型为char /*readonly*/ [3]
。它是具有不变内容的数组。因此,当您想要指向该字符串文字的指针时,应使用指向char const
的指针:
char const *foo = "ab";
这可以防止您意外更改文字。但是,如果您想使用字符串文字来初始化数组:
char foo[] = "ab"; // the size of the array is determined by the initializer
// here: 3 - the characters 'a', 'b' and '\0'
然后可以修改该数组的元素。
数组索引btw只是语法糖:
foo[bar]; /* is the same as */ *(foo + bar);
这就是为什么人们可以做一些有趣的事情
"Hello!"[2]; /* 'l' but also */ 2["Hello!"]; // 'l'