1

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!

Humphrey Bogart
  • 7,423
  • 14
  • 52
  • 59

5 Answers5

5
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
  • 349,597
  • 67
  • 533
  • 578
2
char * whatever = "some cont string";

Is read-only.

ezpz
  • 11,767
  • 6
  • 38
  • 39
2

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
  • 8,920
  • 3
  • 38
  • 56
  • 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 Oct 30 '09 at 01:19
2

See Question 8.5 in the C FAQ list.

Sinan Ünür
  • 116,958
  • 15
  • 196
  • 339
1

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
  • 106,608
  • 13
  • 126
  • 198