Program crashes when trying to set a character of a char array
I got this weird behavior of my programm, that i cant figure out. My professor showed me a flaw in my programm, where i just copy a char pointer when i construct an object instead of making a new copy of the whole array, so you can fool around with it. He demonstrated this with similar code like this.
For the code:
char sweat[] ="Sweater";
warenkorb = new WareImKorb(new Textil (205366,4.2,sweat,40),2,warenkorb);
sweat[0] = '\0';
now if i instead make it:
开发者_如何学Cchar* sweat ="Sweater";
the program runs fine till i try sweat[0] = '\0'; It simply crahes then.
However this works: char cc[] ="Sweater"; char* sweat = cc;
It is really bugging me, that i dont understand, why version 1 does not work. Hope you guys can help me out, or else i will go crazy wondering about this.
"Sweater" is a string literal, which may reside in read-only memory. Using the char[] syntax copies this literal into a char array, using the char * syntax (which really should be const char *) just points at the original string literal.
char* sweat ="Sweater";
sweat[0] = '\0'
Here sweat
points to a CONSTANT data. "Sweater" is const literal data, residing somewhere in read-only memory, and sweat
points to this data as such. It doesn't make a copy of it. So when you do sweat[0]='\0'
, it tries to change first character of the CONSTANT data. Hence the error. By the way, a good compiler should give warning if you don't write const
in your declaration, as const char* sweater = "Sweater"
. See the warning here : http://www.ideone.com/P47vv
But when you write char sweat[] = "Sweater"
, an array of char is created, copying the data from the CONSTANT data which is "Sweater"
; that array's element itself is modifiable!
Lets see an interesting thing: since in the first case, it doesn't make a copy of the const data, so no matter how many variables you declare (all pointing to the same data), the address would be same for all variables. See this:
#include<cstdio>
int main() {
char* sweat ="Sweater"; //notice the warning
const char* another ="Sweater"; //no warning!
std::printf("%p\n", sweat); //print the address
std::printf("%p\n", another); //print the address
return 0;
}
Output:
0x8048610
0x8048610
Means, both printfs print the same address!
See yourself here : http://www.ideone.com/VcyM6
ASCII art to the rescue! The char sweat[]
version looks like this in memory:
+---+---+---+---+---+---+---+---+
sweat: |'S'|'w'|'e'|'a'|'t'|'e'|'r'| 0 | char[8]
+---+---+---+---+---+---+---+---+
Whereas the char* sweat
version looks like this:
+---+---+---+---+---+---+---+---+
|'S'|'w'|'e'|'a'|'t'|'e'|'r'| 0 | const char[8]
+---+---+---+---+---+---+---+---+
^
|
|
+-|-+
sweat: | | | char*
+---+
That's right, a char*
pointing to a const char
. The fact that you can assign a string literal to a non-const character pointer is a nasty holy in C++'s static type system. Curse you, backward compatibility!
In the version that doesn't work, you are not creating any array of chars. You are only playing with pointers.
For sweat[0] = '\0'
to be a valid statement, you need sweat
to be an actual array of chars.
This is done only with char sweat[] = "XXXX";
or char sweat[20];
C++ is not a managed language. Avoid creating pointers to character arrays that don't have a proper size. Both of the following examples are better solutions:
char* sweater = new char[10];
sweater[0] = '\0';
delete [] sweater;
sweater = NULL;
Or better yet:
std::string sweater = "";
精彩评论