tags:

views:

87

answers:

5

How come when I use the following method, to be used to convert 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!

+2  A: 
char * whatever = "some cont string";

Is read-only.

ezpz
+2  A: 

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/

Michael
cheers for the link
Beau Martínez
See http://c-faq.com/aryptr/aryptrequiv.html and http://c-faq.com/aryptr/aryptrparam.html and http://c-faq.com/aryptr/arypbref.html
Sinan Ünür
+6  A: 
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
John Kugelman
is there not a way that only the memory required to hold "la1 4yt" will be allocated in initialising the [mutable] string? declaring it in the array is too verbose for my taste.
Beau Martínez
Sure is, you can omit the size and let the compiler calculate it.
John Kugelman
+1  A: 

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"! */
pmg
cheers on the standard's excerpt!
Beau Martínez
+2  A: 

See Question 8.5 in the C FAQ list.

Sinan Ünür