[英]Why am I able to re-assign a new string to a char pointer in C like so ( ch *string = “hello”; string = “assign”;)
I would like to know why the following code is legal我想知道为什么下面的代码是合法的
char *string = "hello";
string = "changed";
string = "changed again";
This does not cause any problem with the compiler.这不会导致编译器出现任何问题。
But I was under the impression that char arrays initialized as a pointer (char *string as opposed to char string[]) are read-only and cannot be overwritten?但我的印象是 char arrays 初始化为指针(char *string 而不是 char string[])是只读的并且不能被覆盖?
The string data could be laid out like this in memory:字符串数据在 memory 中可以这样布局:
Addr Contents
---- --------
1000 h e l l o \0
1006 c h a n g e d \0
1014 c h a n g e d a g a i n \0
When you initialize the variable string
, it contains the address 1000
.初始化变量
string
时,它包含地址1000
。 The first reassignment changes it to 1006
, the second changes it to 1014
.第一次重新分配将其更改为
1006
,第二次将其更改为1014
。 The string data itself is not being overwritten.字符串数据本身不会被覆盖。
Think about this (explanations to follow).考虑一下(后面的解释)。 There are big differences between
之间存在很大差异
char *string1 = "hello";
char *string2 = "world";
string1 = string2;
and和
char string3[] = "hello";
char string4[] = "world";
strcpy(string3, string4);
and和
char *string5 = "hello";
char *string6 = "world";
strcpy(string5, string6); /* WRONG */
and和
char string7[] = "hello";
char string8[] = "world";
string7 = string8; /* VERY WRONG */
Make sure you understand how the 1/2 and 3/4 cases are different but both work.确保您了解 1/2 和 3/4 案例的不同之处,但两者都有效。 Make sure you understand why both the 5/6 and 7/8 cases are wrong and won't work (but for different reasons).
确保您了解为什么 5/6 和 7/8 案例都是错误的并且不起作用(但出于不同的原因)。
Explanations:说明:
After后
char string3[] = "hello";
char string4[] = "world";
you have two arrays initialized in memory that look like this:你有两个 arrays 在 memory 中初始化,如下所示:
+---+---+---+---+---+---+
string3: | h | e | l | l | o |\0 |
+---+---+---+---+---+---+
+---+---+---+---+---+---+
string4: | w | o | r | l | d |\0 |
+---+---+---+---+---+---+
And after calling打电话后
strcpy(string3, string4);
you end up with你最终得到
+---+---+---+---+---+---+
string3: | w | o | r | l | d |\0 |
+---+---+---+---+---+---+
+---+---+---+---+---+---+
string4: | w | o | r | l | d |\0 |
+---+---+---+---+---+---+
strcpy
copied characters from array4
to array3
. strcpy
将字符从array4
复制到array3
。 (Note, too, that the original string3
and string4
happened to have the same length. It also would have worked if string4
had been shorter, but if string4
had been longer, there would have been an array overflow when copying it to string3
.) (还要注意,原来的
string4
和string3
恰好具有相同的长度。如果string4
更短,它也可以工作,但如果string3
更长,复制到string4
时会出现数组溢出。)
Now to the pointer case.现在到指针案例。 After
后
char *string1 = "hello";
char *string2 = "world";
you have two anonymous arrays, typically in read-only memory, pointed to by two pointer variables that look like this:您有两个匿名 arrays,通常在只读 memory 中,由两个指针变量指向,如下所示:
+-----------+ +---+---+---+---+---+---+
string1: | *----------->| h | e | l | l | o |\0 |
+-----------+ +---+---+---+---+---+---+
+-----------+ +---+---+---+---+---+---+
string2: | *----------->| w | o | r | l | d |\0 |
+-----------+ +---+---+---+---+---+---+
And then after然后之后
string1 = string2;
the pointers are rearranged to look like this:指针重新排列如下:
+-----------+ +---+---+---+---+---+---+
string1: | * | | h | e | l | l | o |\0 |
+-----|-----+ +---+---+---+---+---+---+
|
+--------------+
|
V
+-----------+ +---+---+---+---+---+---+
string2: | *----------->| w | o | r | l | d |\0 |
+-----------+ +---+---+---+---+---+---+
But I was under the impression that char arrays initialized as a pointer (char *string as opposed to char string[]) are read-only and cannot be overwritten?
但我的印象是 char arrays 初始化为指针(char *string 而不是 char string[])是只读的并且不能被覆盖?
Right.正确的。 And that's what goes wrong in the
这就是问题所在
char *string5 = "hello";
char *string6 = "world";
strcpy(string5, string6); /* WRONG */
case.案子。
strcpy
tries to write new characters to string5
, which fails if the pointed-to string has been stored in read-only memory. strcpy
尝试将新字符写入string5
,如果指向的字符串已存储在只读 memory 中,则会失败。 For the same reason you can't do something like出于同样的原因,你不能做类似的事情
string5[0] = 'H'; /* WRONG */
"But I was under the impression that char arrays initialized as a pointer (char *string as opposed to char string[]) are read-only and cannot be overwritten?"
“但我的印象是 char arrays 初始化为指针(char *string 而不是 char string[])是只读的并且不能被覆盖?”
That's "kinda sorta" true, depending on how you look at it.那是“有点”真实的,这取决于你如何看待它。 When the compiler hits an assignment to a literal, it sets aside a bit of memory for the literal and points your
char*
to it.当编译器对文字进行赋值时,它会为文字留出一点 memory 并将您的
char*
指向它。 Depending on compiler and architecture you might not be able to change that memory.根据编译器和体系结构,您可能无法更改 memory。 In all cases you should never try to change that memory (after all you don't know where it's been).
在所有情况下,您都不应该尝试更改 memory(毕竟您不知道它在哪里)。 In that way the actually memory where the string literal (the actual character values) is stored may very well be read-only.
这样,存储字符串文字(实际字符值)的实际 memory 很可能是只读的。
In the case you have shown you aren't changing the memory that contains the characters.在您已经证明您没有更改包含字符的 memory 的情况下。 You are changing the address that
string
points to.您正在更改
string
指向的地址。 Assuming you are defining string
in a function, the value will be allocated on the stack.假设您在 function 中定义
string
,则该值将在堆栈上分配。 It will be sizeof(void *)
and that memory can be changed … it is changed when you change what string
points to.它将是
sizeof(void *)
并且 memory 可以更改……当您更改string
指向的内容时它会更改。 You are changing the address where "changed" is stored to the address where "changed again" is stored.您正在将存储“更改”的地址更改为存储“再次更改”的地址。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.