Thread: Change character in string - legal operation?

  1. #1
    Registered User
    Join Date
    Sep 2016
    Posts
    5

    Change character in string - legal operation?

    Hi,

    i read some articles on the internet and i noticed that changing an character of a string has an undefined behavior. And i also read that if you create a string like that
    Code:
    char string[] = "string";
    that the memory for the string is read-only and you can't change it.
    So i just tested a little bit and on my system it just works fine;
    Code:
    char string[] = "string";
    string[0] = 'S';
    printf("%s\n", string);
    works as expected. It prints out "String". So can someone explain that to me? I am a bit confused right now. Am i just lucky that it works on my machine or did i understand something wrong?

    Thanks Nimmi
    Last edited by Nimmi; 09-28-2016 at 03:23 PM.

  2. #2
    Registered User
    Join Date
    May 2010
    Posts
    4,632
    Am i just lucky that it works
    Yes you are lucky.

    A char can hold one and only one character not a string. A string in C is an array of char terminated by the end of string character.

    Jim

  3. #3
    Registered User
    Join Date
    Sep 2016
    Posts
    5
    Hey Jim,

    thanks for your answer. I just recognized that i forgot to add the braces to the "string" variable. I am sorry, now it should be right.

  4. #4
    Registered User
    Join Date
    May 2010
    Posts
    4,632
    i read some articles on the internet and i noticed that changing an character of a string has an undefined behavior.
    What articles? You can change non-const strings without any problems. However if you try to change a string const you will have problems. Your program seems correct, however something like:
    Code:
        char *cstring = "string";
        cstring[0] = 'S';
    Is ill-formed. In this case the contents of cstring are constant and can't be changed.

    Jim

  5. #5
    Registered User
    Join Date
    Sep 2016
    Posts
    5
    So in general if you create a string like that
    Code:
    char string[9];
    //or
    char string[] = "Hello";
    //or
    char string[6] = "Hello";
    You can change every single character. But if you create a string with a pointer
    Code:
    char *string = "Hello";
    you can't change the characters, right? So i assume that if you create a char pointer then the string is automatically declared as constant?

    Nimmi

  6. #6
    Nasal Demon Xupicor's Avatar
    Join Date
    Sep 2010
    Location
    Poland
    Posts
    179
    So in general if you create a string like that

    Code:
    char string[9];
    string[1] = 'E';
    This is just normal array of chars, it's fine to modify in whatever way you like (with a caveat that if you treat it as a null-terminated string - you have to have a null character ('\0') at the end of your string (notice, that's not necessarily end of your array!). That's because standard string functions will assume that your string is, well, null-terminated.

    Code:
    char string[] = "Hello";
    string[1] = 'E';
    That works too. Here you define an array of chars that will be properly sized based on the string literal. So string will be char[6], and contents of read-only string literal "Hello" will be copied over to it.


    Code:
    char string[6] = "Hello";
    string[1] = 'E';
    That works as well. Here you define an array of chars with length of 6 and the contents of read-only string literal "Hello" will be copied over to it. Notice, though, that if you'd make it char[5] - the terminating character won't be copied over, and you will have to add it yourself. It's safer to omit array size here, make the compiler count the characters for you.

    So i assume that if you create a char pointer then the string is automatically declared as constant?
    No, it has nothing to do with pointers - rather with the thing you're pointing to - the string literal.

    Code:
    char* string = "Hello";
    string[1] = 'E';
    If that works - then it's by sheer luck, or blessing of the Chaos Gods. What you have here is string is a pointer to char, and you assign to it the address of a read-only string literal. In itself, that's fine, because C - even in It'll probably compile fine, but during runtime it may do whatever Chaos Gods wish it. I get a segmentation fault. Phew, lucky.

    Standardese about string literals:
    [6.4.5 String literals N1570, C11]
    7 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.
    [...]
    32 On the other hand, the declaration
    Code:
    char *p = "abc";
    defines p with type ‘‘pointer to char’’ and initializes it to point to an object with type ‘‘array of char’’ with length 4 whose elements are initialized with a character string literal. If an attempt is made to use p to modify the contents of the array, the behavior is undefined.[/quote]
    You can still safely use pointers to string literals though, and make your compiler scream at you if you attempt to modify a string literal through such a pointer - just make 'em const:
    Code:
    const char* p = "hello world!";
    p[1] = 'E'; //  error: assignment of read-only location
    Here's an example of using a pointer:
    Code:
        char* p = malloc(10); //dynamically allocated memory    strcpy(p, "yolo!");
        puts(p);
        free(p); 
        
        char foo[] = "Hello!";
        char* bar = foo;
        bar[1] = 'E';
        puts(foo);
        puts(bar);
        
        const char* fubar = foo;
        fubar[1] = 'e'; //kaboom!

  7. #7
    Registered User
    Join Date
    Sep 2016
    Posts
    5
    Thank you so much. That really helped me a lot. I think i got it now.

    Nimmi

  8. #8
    Registered User
    Join Date
    May 2012
    Posts
    505
    You've been given half the story.

    In old C, there was no "const" and
    Code:
     char *string = "string"
    would create the pattern 's', 't', 'r', 'i', 'n', 'g', '0' in memory. You could then write to it in the normal way.

    But C compilers started putting string tables in read-only regions of memory. So string literals (a literal means a string in quotes in the source code) became constant by default. But they were still char * instead of const char * to avoid breaking old code. That created a rather undesirable, confusing situation. Finally, if you want a string to be mutable

    Code:
    char string[i] = "string";
    Will create a read/write string in memory, like the old behaviour. It's not very intuitive. However in real programs you very seldom want to modify a string literal.
    I'm the author of MiniBasic: How to write a script interpreter and Basic Algorithms
    Visit my website for lots of associated C programming resources.
    https://github.com/MalcolmMcLean


  9. #9
    Registered User
    Join Date
    Sep 2016
    Posts
    5
    Well, that makes sense.

    Thank you very much for your help.

  10. #10
    Nasal Demon Xupicor's Avatar
    Join Date
    Sep 2010
    Location
    Poland
    Posts
    179
    Just to add some perspective: "old C" Malcolm refers to is at least pre-1988.
    Brian Kernighan and Dennis Ritchie in second edition of "The C Programming Language" (stamped with "ANSI C" on the cover) say:
    Whether identical string literals are distinct is implementation-defined, and the behavior of a program that attempts to alter a string literal is undefined.
    Again, that was published in 1988, a year before ANSI C standard was completed and ratified (it was worked on since 1983, while C was developed by K&R around 69-73). Modifying the string literal was UB at least ever since then, so for 28 years now.

    I've skimmed through K&R1 (1978) to see if it has anything on the topic, but it doesn't seem so, or at least I haven't found anything. String literal is also called string constant there, but neither code examples nor the text seem to either show manipulation of it by means of pointer-to-char, or to say anything about such manipulation being permitted or not. Malcolm might have referred to this "K&R C", however I'm not old enough to actually be using any compiler from those times to know what they allowed or not.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. How to initialize string one by one in legal way
    By raj21 in forum C Programming
    Replies: 4
    Last Post: 09-10-2015, 10:53 AM
  2. Casting *string to *char legal?
    By Programmer_P in forum C++ Programming
    Replies: 5
    Last Post: 06-01-2010, 12:53 AM
  3. how to change this simple opeation into power operation..
    By transgalactic2 in forum C Programming
    Replies: 9
    Last Post: 12-20-2008, 03:17 PM
  4. Change character in file?
    By rkooij in forum C Programming
    Replies: 7
    Last Post: 05-10-2007, 09:57 AM
  5. change character while in scanf
    By Beginnerinc in forum C Programming
    Replies: 1
    Last Post: 05-29-2003, 11:43 AM

Tags for this Thread