简体   繁体   English

为什么我能够像这样将新字符串重新分配给 C 中的 char 指针(ch *string = “hello”; string = “assign”;)

[英]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 .) (还要注意,原来的string4string3恰好具有相同的长度。如果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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM