所以我有以下程序:
int main(){ char* one = "computer"; char two[] = "another"; two[1]='b'; one[1]='b'; return 0; }
它在“ one [1] =’b’”行上进行段错误,这是有道理的,因为指针“ one”指向的内存必须位于只读内存中。但是,问题是,为什么“ two [1] =’b’” segfault行没有出现?查看gcc的程序集输出:
.file "one.c" .section .rodata .LC0: .string "computer" .LC1: .string "another" .text .globl main .type main, @function main:
我们看到两个字符串都在rodata部分中,因此它们是只读的。那么,为什么“ two [1] =’b’行不存在段错误”呢?
one直接指向位于只读页面中的字符串。另一方面,two是在堆栈上分配的数组,并使用一些常量数据进行初始化。在运行时,可执行文件的只读部分中的字符串将被复制到堆栈中。您要修改的是该字符串在堆栈上的副本,而不是只读存储器页面。
one
two
从语言的角度来看,在更高层次上"abcd"是type const char*而不是的表达char*。因此,修改此类表达式所指向的值会导致未定义的行为。该语句char* one = "something";仅将指向字符串的指针存储在变量中(不安全,因为它正在抛弃const修饰符)。的char two[] = "something";是完全不同的。它实际上是在声明一个数组并对其进行初始化,就像int a[] = {1,2,3};。引号中的字符串是初始化表达式。
"abcd"
const char*
char*
char* one = "something";
const
char two[] = "something";
int a[] = {1,2,3};