Thread: Change one element of string pointed by char pointer

  1. #1
    Registered User
    Join Date
    Dec 2007
    Posts
    932

    Change one element of string pointed by char pointer

    I know how to change a char in a char array but I wonder if we can change one element of a C-string pointed by a char pointer?

    Code:
    int main()
    {
        char * p = "Hello World";
        *(p+1) = 'x';
    
        cout << p << endl;
    
        return 0;
    }
    Using Windows 10 with Code Blocks and MingW.

  2. #2
    SAMARAS std10093's Avatar
    Join Date
    Jan 2011
    Location
    Nice, France
    Posts
    2,692
    Well, I feel a bit strange to see a guy with 643 posts not using class string in C++.

    You handle strings the C way. And of course, no. You can use some flag in the compilation procedure to allow this to happen.

    Why? Because this is a string literal! String literals can not modify their data, but they can modify their pointer.

    On the other hand, if you had an array, then the opposite stands true. You can not modify the pointer, but you can modify the data
    Code - functions and small libraries I use


    It’s 2014 and I still use printf() for debugging.


    "Programs must be written for people to read, and only incidentally for machines to execute. " —Harold Abelson

  3. #3
    Registered User
    Join Date
    Sep 2008
    Posts
    200
    Quote Originally Posted by Ducky View Post
    I know how to change a char in a char array but I wonder if we can change one element of a C-string pointed by a char pointer?

    Code:
    int main()
    {
        char * p = "Hello World";
        *(p+1) = 'x';
    
        cout << p << endl;
    
        return 0;
    }
    Yes, but that code will probably result in a segment violation - in this case, `p' should realy be `const char *' since initializing it like this may place the string in read-only memory. Initializing it as an array will place it on the stack where it can be treated as a `char *'.

    In short, change your definition of `p' to:

    Code:
    char p[] = "Hello World";
    Programming and other random guff: cat /dev/thoughts > blogspot.com (previously prognix.blogspot.com)

    ~~~

    "The largest-scale pattern in the history of Unix is this: when and where Unix has adhered most closely to open-source practices, it has prospered. Attempts to proprietarize it have invariably resulted in stagnation and decline."

    Eric Raymond, The Art of Unix Programming

  4. #4
    SAMARAS std10093's Avatar
    Join Date
    Jan 2011
    Location
    Nice, France
    Posts
    2,692
    Example with string literal.

    Code:
    #include <stdio.h>
    
    int main(void)
    {
        char* strLiteral = "I am a string literal!";
        char* origin = strLiteral;
    
        printf("I am about to chrash...!\n");
        *(strLiteral+1) = 'W';
        printf("Did I?\n");
    
        printf("%s\n", origin);
    
        return 0;
    }
    Output
    Code:
    linux05:/home/users/std10093>px
    I am about to chrash...!
    Segmentation fault
    While with the array
    Code:
    #include <stdio.h>
    
    int main(void)
    {
        char str[15] = "a string";
        
        printf("I can modify the data...\n");
        *(str+1) = 'W';
        
        printf("But not the pointer...!\n");
        str++;
        
        printf("%s\n", str);
        
        return 0;
    }
    On linux I got output:
    Code:
    linux05:/home/users/std10093>gcc -Wall px.c -o px
    px.c: In function 'main':
    px.c:11: error: lvalue required as increment operand
    and on windows
    Code:
    main.c: In function `main':
    main.c:11: error: wrong type argument to increment
    make[2]: *** [build/Debug/Cygwin-Windows/main.o] Error 1
    make[1]: *** [.build-conf] Error 2
    make: *** [.build-impl] Error 2
    Hope that helps!
    Code - functions and small libraries I use


    It’s 2014 and I still use printf() for debugging.


    "Programs must be written for people to read, and only incidentally for machines to execute. " —Harold Abelson

  5. #5
    Registered User
    Join Date
    Dec 2007
    Posts
    932
    Thank you, that helped.
    Using Windows 10 with Code Blocks and MingW.

  6. #6
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,653
    So why are you using C strings, now?
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  7. #7
    SAMARAS std10093's Avatar
    Join Date
    Jan 2011
    Location
    Nice, France
    Posts
    2,692
    Maybe he uses the string class, but wanted to remember how it feels handling strings in C way :P
    Code - functions and small libraries I use


    It’s 2014 and I still use printf() for debugging.


    "Programs must be written for people to read, and only incidentally for machines to execute. " —Harold Abelson

  8. #8
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,653
    Let's not assume things... though, when these things show up, I get kind of worried that Ducky is trying to climb up the wrong path again...
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  9. #9
    Registered User
    Join Date
    Oct 2006
    Posts
    3,443
    Quote Originally Posted by Ducky View Post
    Code:
    char * p = "Hello World";
    actually, on g++, this code will give compiler warnings about this conversion being deprecated.

    Code:
    char p[] = "Hello World";
    is fine though, as is

    Code:
    const char * p = "Hello World";

  10. #10
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,611
    Quote Originally Posted by std10093 View Post
    String literals can not modify their data, but they can modify their pointer.

    On the other hand, if you had an array, then the opposite stands true. You can not modify the pointer, but you can modify the data
    I'd prefer to say that a pointer can change its string literal. I wouldn't really say that, it sounds awkward, but the point is that string literal should be pointed to, it doesn't own it's own pointer and the data itself doesn't really decay into a pointer. A string literal is actually "This" or "this" -- objects of type char[5] -- the data proper.

    char *p = "This";

    p can be reassigned, because it is a pointer. And that very syntax is only allowed as a convenience. A convenience which C++ copied from the beginning, I think, but nonetheless. Before C was standardized, you needed to do magic like this:

    char * p;
    char cs[] = "This";
    p = cs;

    I will even link a FAQ answer later that shows the difference between a pointer pointing to an array object and an array itself with pictures.

    Quote Originally Posted by std10093 View Post
    Example with string literal.
    <snip>

    While with the array
    Code:
    #include <stdio.h>
    
    int main(void)
    {
        char str[15] = "a string";
        
        printf("I can modify the data...\n");
        *(str+1) = 'W';
        
        printf("But not the pointer...!\n");
        str++;
        
        printf("%s\n", str);
        
        return 0;
    }
    On linux I got output:
    Code:
    linux05:/home/users/std10093>gcc -Wall px.c -o px
    px.c: In function 'main':
    px.c:11: error: lvalue required as increment operand
    and on windows
    Code:
    main.c: In function `main':
    main.c:11: error: wrong type argument to increment
    make[2]: *** [build/Debug/Cygwin-Windows/main.o] Error 1
    make[1]: *** [.build-conf] Error 2
    make: *** [.build-impl] Error 2
    Hope that helps!
    This code that you posted is actually guaranteed not to work.
    Arrays cannot be reassigned, because that's illegal. If arrays were pointers, then it would be legal. str++; is:

    str = str + 1;

    which means that this requires array assignment. With a pointer, this operation is fine, though it's not guaranteed to point to a dereferenceable location. In other words, you can do this:
    Code:
    #include <stdio.h>
    #include <ctype.h>
    
    int main(void) {
       char foo[] = "My sample string.";
    
       for (char *bar = foo; *bar != '\0'; bar++) {
          *bar = toupper(*bar);
       }
       printf("%s\n", foo);
       
       return 0;
    }
    But you cannot increment foo here, because foo is an array type. Try, and you will get that error. foo is the wrong type to increment.

    Try reading this FAQ answer.
    Last edited by whiteflags; 02-15-2013 at 01:01 AM.

  11. #11
    Registered User
    Join Date
    Jun 2005
    Posts
    6,814
    Quote Originally Posted by Elysia View Post
    Let's not assume things... though, when these things show up, I get kind of worried that Ducky is trying to climb up the wrong path again...
    Ducks waddle, not climb.
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  12. #12
    Registered User
    Join Date
    Dec 2007
    Posts
    932
    lol
    @Elysia

    I was looking at somebody's code and I was wondering why was that working when 'pa' is declared as a pointer so the value it was pointing couldn't be changed.
    Is it because of VirtualProtect()?
    Code:
        DWORD_PTR pa = 0x12340011;
        BYTE *p = (BYTE *)pa;
    
        VirtualProtect((void *)pa,5,
                            PAGE_EXECUTE_READWRITE,&OldProtect);
    
        p[0] = (BYTE)0xE9;
        for (int i = 0; i < 4; i++)
            p[i + 1] = p2[i];
    Using Windows 10 with Code Blocks and MingW.

  13. #13
    SAMARAS std10093's Avatar
    Join Date
    Jan 2011
    Location
    Nice, France
    Posts
    2,692
    It's because it is of type void, so you can't have an array of type void, but a pointer to void!

    Elysia, I told that in terms of fun mostly, don't get so upset
    Code - functions and small libraries I use


    It’s 2014 and I still use printf() for debugging.


    "Programs must be written for people to read, and only incidentally for machines to execute. " —Harold Abelson

  14. #14
    SAMARAS std10093's Avatar
    Join Date
    Jan 2011
    Location
    Nice, France
    Posts
    2,692
    Quote Originally Posted by whiteflags View Post
    I'd prefer to say that a pointer can change its string literal. I wouldn't really say that, it sounds awkward, but the point is that string literal should be pointed to, it doesn't own it's own pointer and the data itself doesn't really decay into a pointer. A string literal is actually "This" or "this" -- objects of type char[5] -- the data proper.
    The more you know something, the easier you can explain. I believe that you have a good knowledge, so rephrase what you said.
    Quote Originally Posted by whiteflags View Post
    p can be reassigned, because it is a pointer.
    Ι believe I said that too.
    Quote Originally Posted by whiteflags View Post
    I will even link a FAQ answer later that shows the difference between a pointer pointing to an array object and an array itself with pictures.
    That is what I am trying to say... but thanks for the FAQ, since I didn't know about this page.
    Quote Originally Posted by whiteflags View Post
    This code that you posted is actually guaranteed not to work.
    Arrays cannot be reassigned, because that's illegal. If arrays were pointers, then it would be legal. str++; is:

    str = str + 1;

    which means that this requires array assignment. With a pointer, this operation is fine, though it's not guaranteed to point to a dereferenceable location. In other words, you can do this:
    Code:
    #include <stdio.h>
    #include <ctype.h>
    
    int main(void) {
       char foo[] = "My sample string.";
    
       for (char *bar = foo; *bar != '\0'; bar++) {
          *bar = toupper(*bar);
       }
       printf("%s\n", foo);
       
       return 0;
    }
    But you cannot increment foo here, because foo is an array type. Try, and you will get that error. foo is the wrong type to increment.
    Exactly! The code I posted was for demonstration of which you can do and what you can't! I thought this was clear by the printfs

    However, I like your example, so I am going to augment my upload on my page with your example and the faq link. Of course you will get the credits

    EDIT: Here it is.
    Last edited by std10093; 02-15-2013 at 06:52 AM.
    Code - functions and small libraries I use


    It’s 2014 and I still use printf() for debugging.


    "Programs must be written for people to read, and only incidentally for machines to execute. " —Harold Abelson

  15. #15
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,611
    Quote Originally Posted by std10093 View Post
    The more you know something, the easier you can explain. I believe that you have a good knowledge, so rephrase what you said.
    I hope you are doing this because you didn't understand me somehow.

    String literals have a type. It's array of char. And while you said "String literals can not modify their data, but they can modify their pointer," my main problem with this is that they don't have a pointer like you implied. The pointer and the string literal are actually separate things.

    Ι believe I said that too.

    That is what I am trying to say... but thanks for the FAQ, since I didn't know about this page.

    Exactly! The code I posted was for demonstration of which you can do and what you can't! I thought this was clear by the printfs

    However, I like your example, so I am going to augment my upload on my page with your example and the faq link. Of course you will get the credits
    Please. I give 0 ........s about credit here.

    If you were trying to say what I said, I felt I needed to rephrase your post anyway. You kept referring to arrays as pointers. Arrays are not pointers. And I thought it was important enough to say that arrays in general can't be reassigned, and it's not just a string literal issue.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 3
    Last Post: 01-15-2012, 06:09 AM
  2. Adreess of pointed structure element
    By limp in forum C Programming
    Replies: 1
    Last Post: 06-12-2009, 05:54 AM
  3. How change value pointed to by shared_ptr?
    By 6tr6tr in forum C++ Programming
    Replies: 1
    Last Post: 04-28-2008, 03:45 PM
  4. Problem with passing back pointer pointed to string
    By whichet in forum C Programming
    Replies: 9
    Last Post: 11-21-2007, 07:55 AM
  5. Replies: 5
    Last Post: 10-29-2001, 10:16 AM