Thread: Why does this code fail?

  1. #1
    Registered User
    Join Date
    Sep 2003
    Posts
    224

    Why does this code fail?

    This fails:
    Code:
    char *s = "hello";
    s[0] = 'H';
    but this doesn't:
    Code:
    char s[] = "hello";
    s[0] = 'H';
    or this:
    Code:
    char *s = "hello";
    printf("%c\n", s[0]);
    Besides being a constant pointer, I've always thought char [] was equivalent to char *.

  2. #2
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by Yasir_Malik View Post
    Besides being a constant pointer, I've always thought char [] was equivalent to char *.
    And you have now discovered that it's not.

  3. #3
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    I thought I wrote a reply earlier...

    Can you please describe what you mean by "fails", as I don't see anything that is OBVIOUSLY wrong with your code. But "fails" and "works" are fairly broad terms - "works" could mean that it doesn't crash, but if it comes up with $-1927489231.32 as my "balance" after I've paid this months electrics bill, it may not be quite "working correctly" - so it failed on the next level: operating CORECTLY!

    Also, it would help if you could give a little more code around these code-snippets, because it may be something else that is making it go wrong...

    --
    Mats

  4. #4
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by matsp View Post
    Can you please describe what you mean by "fails"
    I assume it crashes. You can't modify a string literal on most platforms.

  5. #5
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by brewbuck View Post
    I assume it crashes. You can't modify a string literal on most platforms.
    Ah, yes, it crashes on my machine too - for that very reason, the string appears to be in "code" (or is it called "text") memory, so it can't be written to.

    --
    Mats

  6. #6
    Registered User
    Join Date
    Sep 2003
    Posts
    224
    But why does assigning to an index in char str[] work? Is there something special about char *str that puts the string into the text memory, not into data memory?

  7. #7
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Code:
    char s[] = "something";
    creates an array of char that is long enough to hold "something", and initialized to that value. Since the variable "s" is in data-memory, and it's containing "something", it can be written to.

    Code:
    char *s = "something"
    creates a pointer s, that points to the constant string "something". Since "something" is a constant, it's not expected to be written to.

    Similarly if you do a function-call:
    Code:
    void blah(char *s)
    {
       ...
    }
    
    ...
        blah("something");
    ...
    blah can't change the input string [and some compilers may catch that by saying "loosing const attribute" or some such].

    --
    Mats

  8. #8
    Registered User
    Join Date
    Sep 2003
    Posts
    224
    I see now. It goes back to how char s[] is a constant pointer while char *p is just a pointer. Since it can point to anything, it would pointless to have the string "something" floating around; otherwise, there would be a memory leak if I did char *p = "asdf" multiple times in a function.

  9. #9
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    Quote Originally Posted by Yasir_Malik View Post
    I see now. It goes back to how char s[] is a constant pointer while char *p is just a pointer. Since it can point to anything, it would pointless to have the string "something" floating around; otherwise, there would be a memory leak if I did char *p = "asdf" multiple times in a function.
    Code:
    char s[] = "hello";
    is the same as
    Code:
    char s[6] = "hello";
    Leaving out the 6 just means that the compiler must infer the size from the thing after the equals.
    I.e. s is a variable that holds an array of 6 chars. Those chars are initialised to the string "hello" (i.e. copied into the buffer), but you're free to overwrite them as you please.
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  10. #10
    Deathray Engineer MacGyver's Avatar
    Join Date
    Mar 2007
    Posts
    3,210
    Simply put, allocating the array provides the space for the string literal to be automatically copied to. This copy is done automatically behind the scenes. If you use a straight pointer, you end up pointing to wherever the string literal is stored, which is generally in read-only memory.

  11. #11
    Registered User
    Join Date
    Sep 2003
    Posts
    224
    I was thinking about doing this many times:
    Code:
    void func(void)
    {
     char *s = "hello";
    }
    If the compiler allocated memory for s in the data segment. Eventually there would be "hello"s everywhere.
    In addition, s can point to anywhere, so it could point to another char * later on in the code. "hello" would be lost and so would that memory; you can't call delete or free on that. Instead, allocate "hello" once in the text segment.

  12. #12
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by Yasir_Malik View Post
    I see now. It goes back to how char s[] is a constant pointer while char *p is just a pointer.
    char s[] is not a "constant pointer." It is an array. The name of the array acts like a constant pointer in an R-value context. That's the relationship, not more, not less.

    The reason the char s[] version is writable is precisely BECAUSE it is an array.

  13. #13
    Registered User hk_mp5kpdw's Avatar
    Join Date
    Jan 2002
    Location
    Northern Virginia/Washington DC Metropolitan Area
    Posts
    3,817
    Quote Originally Posted by Yasir_Malik View Post
    I was thinking about doing this many times:
    Code:
    void func(void)
    {
     char *s = "hello";
    }
    If the compiler allocated memory for s in the data segment. Eventually there would be "hello"s everywhere.
    In addition, s can point to anywhere, so it could point to another char * later on in the code. "hello" would be lost and so would that memory; you can't call delete or free on that. Instead, allocate "hello" once in the text segment.
    Memory for s (the actual pointer itself) is allocated from the stack when the function is called. The memory it points to, where the string "hello" resides and the address of which is assigned to s, is in the data segment which is read-only.
    "Owners of dogs will have noticed that, if you provide them with food and water and shelter and affection, they will think you are god. Whereas owners of cats are compelled to realize that, if you provide them with food and water and shelter and affection, they draw the conclusion that they are gods."
    -Christopher Hitchens

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Extended ASCII Characters in an RTF Control
    By JustMax in forum C Programming
    Replies: 18
    Last Post: 04-03-2009, 08:20 PM
  2. Enforcing Machine Code Restrictions?
    By SMurf in forum Tech Board
    Replies: 21
    Last Post: 03-30-2009, 07:34 AM
  3. Obfuscated Code Contest
    By Stack Overflow in forum Contests Board
    Replies: 51
    Last Post: 01-21-2005, 04:17 PM
  4. Interface Question
    By smog890 in forum C Programming
    Replies: 11
    Last Post: 06-03-2002, 05:06 PM
  5. Replies: 0
    Last Post: 02-21-2002, 06:05 PM