开发者

Different string initialization yields different behavior?

How come when I use the following method, to be used to convert开发者_JAVA技巧 all the characters in a string to uppercase,

while (*postcode) {
    *postcode = toupper(*postcode);

    postcode++;
}

Using the following argument works,

char wrong[20];
strcpy(wrong, "la1 4yt");

But the following, doesn't, despite them being the same?

char* wrong = "la1 4yt";

My program crashes in an attempt to write to an illegal address (a segfault, I presume). Is it an issue with not mallocing? Not being null-terimanted? It shouldn't be...

Through debugging I notice it crashes on the attempt to assign the first character as its uppercase.

Any help appreciated!


char* wrong = "la1 4yt";

This declares a pointer to a string constant. The constant cannot be modified, which is why your code crashes. If you wrote the more pedantic

const char* wrong = "la1 4yt"; // Better

then the compiler would catch the mistake. You should probably do this any time you declare a pointer to a string literal rather than creating an array.

This, on the other hand, allocates read/write storage for twenty characters so writing to the space is fine.

char wrong[20];

If you wanted to initialize it to the string above you could do so and then would be allowed to change it.

char wrong[20] = "la1 4yt"; // Can be modified
char wrong[]   = "la1 4yt"; // Can be modified; only as large as required


char * whatever = "some cont string";

Is read-only.


In the second variant, "la1 4yt" is a constant and therefore is in a read-only segment. Only the pointer (wrong) to the constant is writeable. That's why you get the segfault. In the first example however, everything is writable.

This one might be interesting: http://eli.thegreenplace.net/2009/10/21/are-pointers-and-arrays-equivalent-in-c/


See Question 8.5 in the C FAQ list.


When you do

char wrong[20] = "la1 4yt";

the compiler copies the elements of the string literal {'l', 'a', '1', ' ', '4', 'y', 't', '\0'} to the corresponding elements of the wrong array; when you do

char *wrong = "la1 4yt";

the compiler assigns to wrong the address of the string literal.

String literals are char[] (arrays of char), not const char[] ... but you cannot change them!!

Quote from the Standard:

6.4.5 String literals
6   It is unspecified whether these arrays are distinct provided
    their elements have the appropriate values. If the program
    attempts to modify such an array, the behavior is undefined.

When I use a string literal to initialize a char *, I usually also tell the compiler I will not be changing the contents of that string literal by adding a const to the definition.

const char *wrong = "la1 4yt";

Edit

Suppose you had

char *test1 = "example test";
char *test2 = "test";

And the compiler created 1 single string literal and used that single string literal to initialize both test1 and test2. If you were allowed to change the string literal ...

test1[10] = 'x';       /* attempt to change the 's' */
printf("%s\n", test2); /* print "text", not "test"! */
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜