常量记忆
由于字符串文字在设计上是只读的,因此它们存储在常数部分的记忆。存储在那里的数据是不可变的,即不能更改。因此,在 C 代码中定义的所有字符串文字都在这里获得一个只读内存地址。
栈内存
这堆栈部分内存是局部变量地址所在的地方,例如,函数中定义的变量。
正如@matli 的回答所暗示的那样,有两种方法可以使用 string 这些常量字符串。
1. 指向字符串文字的指针
当我们定义一个指向字符串文字的指针时,我们正在创建一个指针变量,它位于栈内存.它指向底层字符串文字所在的只读地址。
#include <stdio.h>
int main(void) {
char *s = "hello";
printf("%p
", &s); // Prints a read-only address, e.g. 0x7ffc8e224620
return 0;
}
如果我们尝试通过插入来修改s
s[0] = 'H';
我们得到一个Segmentation fault (core dumped)。我们正在尝试访问我们不应该访问的内存。我们正在尝试修改只读地址 0x7ffc8e224620 的值。
2.字符数组
为了示例,假设存储在常量内存中的字符串文字"Hello" 具有与上面相同的只读内存地址0x7ffc8e224620。
#include <stdio.h>
int main(void) {
// We create an array from a string literal with address 0x7ffc8e224620.
// C initializes an array variable in the stack, let's give it address
// 0x7ffc7a9a9db2.
// C then copies the read-only value from 0x7ffc8e224620 into
// 0x7ffc7a9a9db2 to give us a local copy we can mutate.
char a[] = "hello";
// We can now mutate the local copy
a[0] = 'H';
printf("%p
", &a); // Prints the Stack address, e.g. 0x7ffc7a9a9db2
printf("%s
", a); // Prints "Hello"
return 0;
}
笔记:在 1. 中使用指向字符串文字的指针时,最佳做法是使用 const 关键字,例如 const *s = "hello"。这更具可读性,编译器将在违反时提供更好的帮助。然后它会抛出类似 error: assignment of read-only location ‘*s’ 的错误,而不是段错误。在您手动编译代码之前,编辑器中的 Linters 也可能会发现错误。