String constants vs char arrays in C [duplicate]

2019-04-13 14:27发布

问题:

Possible Duplicate:
What is the difference between char s[] and char *s in C?

More of a general question rather than trying to fix something, I've been reading the C programming language book and they take care to make the distinction between

char amessage[] = "blah";
char *pmessage = "blah";

The difference being one is a char array and the other a pointer to a string constant. They say modifying the char array is acceptable but you shouldn't modify string constants as it triggers undefined behavior. My question is: isn't the string constant stored in memory the same way the char array is? Why can I modify it as in

char *p = "this is a string constant";
*(p+2) = 'a';
printf("%s", p);

Ends up printing "thas is a string constant" as you might expect. I can understand how it would make sense as a string constant shouldn't end up being changed at run time, as it might confuse others/yourself working on your code not expecting it's value to change but in purely functional terms what is wrong with it, what is the undefined behavior that might trigger and how mechanically could it backfire when a char array wouldn't? I'm just wondering if I'm missing something about how string constants work in memory and how they are seen by the compiler.

回答1:

At least on my computer, the following program crashes:

#include <stdio.h>
int main() { 
  char *p = "this is a string constant";
  *(p+2) = 'a';
  printf("%s", p);
}

If it appears to be working for you (which it might on certain embedded compilers), you're just getting lucky. Undefined behavior means the program is allowed to do anything. See http://blog.regehr.org/archives/213 .

See also What is the difference between char s[] and char *s?.



回答2:

In case of char array the content of the string literal "blah" are copied on to the stack as well. So you can modify it without invoking UB because after all its just a copy.

In case of char * you actually try to modify the original string literal and as per the Standard that is UB.



回答3:

With a string constant, there's not guarantee about where the data will be stored -- the compiler is free to do any tricks it wants, because you're supposed to be forbidden from writing to it. So for example, it's not unheard of for the pointer to actually point to the spot in the loaded executable code itself where the string constant is defined.