views:

91

answers:

2

I have two pointers to the same C string. If I increment the second pointer by one, and assign the value of the second pointer to that of the first, I expect the first character of the first string to be changed. For example:

#include "stdio.h"

int main() {
  char* original_str = "ABC";        // Get pointer to "ABC"
  char* off_by_one = original_str;   // Duplicate pointer to "ABC"
  off_by_one++;                      // Increment duplicate by one: now "BC"
  *original_str = *off_by_one;       // Set 1st char of one to 1st char of other
  printf("%s\n", original_str);      // Prints "ABC" (why not "BBC"?)
  *original_str = *(off_by_one + 1); // Set 1st char of one to 2nd char of other
  printf("%s\n", original_str);      // Prints "ABC" (why not "CBC"?)

  return 0;
}

This doesn't work. I'm sure I'm missing something obvious - I have very, very little experience with C.

Thanks for your help!

+8  A: 

You are attempting to modify a string literal; string literals are not modifiable (i.e., they are read-only).

Your code declares original_string as a pointer to the string literal "ABC":

char* original_string = "ABC";

If you change this to:

char original_string[] = "ABC";

you should be good to go. This declares an array of char that is initialized with the contents of the string literal "ABC". The array is automatically given a size of four elements (at compile-time), because that is the size required to hold the string literal (including the null terminator).

James McNellis
Wonderful, thanks!
Kiwi
How is it not modifiable? I'm not arguing that it is, but I'm wondering what keeps the string literal immutable. Does the compiler enforce it? If so, then why isn't this a compiler error? Is the literal located in a block of memory that the OS has marked as read only?
A. Levy
@A. Levy: Well, it is "not modifiable" because the language standard states that modifying the string literal results in undefined behavior. In many implementations, string literals are placed in some block of memory flagged read-only, so you get a segmentation fault or access violation of some kind if you try to write to it.
James McNellis
@A.Levy: The C Standard "keeps" the string literal immutable, because it is undefined behaviour to modify it. Of course a compiler can store it in a modifiable region of memory, allowing modifications to work, which is valid undefined behaviour. It may as well blow up the universe (which is valid ub too), so whenever you see `char *s = "literal";` you know that either `const char *s` or `char s[]` was meant.
Secure
In this particular case, the two `printf` statements might well have been optimised down to `puts("ABC")` (since the compiler can see that the pointer itself is never changed, and it's allowed to rely on the non-modifiability of string literals).
caf
+1  A: 

The problem is that you can't modify the literal "ABC", which is read only.

Try char[] original_string = "ABC", which uses an array to hold the string that you can modify.

Christian