string modification

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • jerico
    New Member
    • Sep 2006
    • 39

    string modification

    Hi all.I could not understand why the following program didn't work.Please explain.

    int main()
    {
    char *t="hello",*r;
    r=t;
    *r='H';
    printf("%s",t);
    return 0;
    }
    It results in segmentation fault.Bye.

    Regards,
    Jerico
  • tyreld
    New Member
    • Sep 2006
    • 144

    #2
    Originally posted by jerico
    Hi all.I could not understand why the following program didn't work.Please explain.

    int main()
    {
    char *t="hello",*r;
    r=t;
    *r='H';
    printf("%s",t);
    return 0;
    }
    It results in segmentation fault.Bye.

    Regards,
    Jerico
    The problem is that the memory allocated for "hello" is in the programs data segment and is therefore protected and any attempt to modify it will result in a segmentation fault.. You can get around this by using the strdup function. This will create a duplicate in the heap that you can freely modify.

    Code:
    #include <string.h>  // this is the header that contains strdup
    
    ...
    
    char *t = strdup("hello");

    Comment

    • anupam
      New Member
      • Aug 2006
      • 12

      #3
      Hi jerico,

      int main()
      {
      char *t="hello",*r;
      r=t;
      *r='H';
      printf("%s",t);
      return 0;
      }

      I could not understand ur motivation. If you wanted to reassign some string then its not possible to update a constant data.

      By the way where r u from?

      Comment

      • dush
        New Member
        • Sep 2006
        • 27

        #4
        I see it in this way:

        int main()
        {
        // char *t="hello",*r;
        // "hello" is considered as const, so it is in the data segment and it cannot be changed
        char t[]="hello",*r;
        // "hello" is considered as array, so it is in the stack (if you prefer heap use strdup)
        r=t;
        *r='H';
        printf("%s",t);
        return 0;
        }

        Comment

        • jerico
          New Member
          • Sep 2006
          • 39

          #5
          Thanks for the answer.But I could not understand the data segment part.Does it mean that all things pointed by pointers are stored in the data segment?

          Regards,
          jerico

          Comment

          • Banfa
            Recognized Expert Expert
            • Feb 2006
            • 9067

            #6
            No actually it's got nothing to do with pointers.

            All literals are constant, you can change the value of the string literal "hello" in the same way that you can't change the value of an integer literal 5.

            You can set a pointer to a string literal (something you can't do for other literals like integers) but you can not use that pointer to modify the literal.

            If you point you pointer at a piece of allocated data (from the stack or the heap or else where) then you can alter the data through the pointer.

            In fact in some systems you can alter the value of string literals but it is still a bad idea.

            char *pszText = "Hello";

            allocates a pointer that is set to the value of the location of the string literal "Hello";

            char pszText[] = "Hello";

            allocates 6 (enough) bytes of data and copies the string literal "Hello" into it.

            Comment

            • dush
              New Member
              • Sep 2006
              • 27

              #7
              "Does it mean that all things pointed by pointers are stored in the data segment?"

              No, it doesnt.

              Pointer stores address of memory. It means it can point anywhere in memory (heap, stack, data segment). What you did in your example was you let your pointer t (and later pointer r too) point to data segment memory address where const string "hello" was placed.
              Data segment is part of program memory where are constants and some more things(like static variables) stored.

              You are able to read char value on this address by dereferencing your pointer r or t, but you are not allowed to change that value.

              1.)
              char *t="hello";
              /* constant string terminated with '\0' is created in data segment and pointer t of char type is declared and initialized with memory address where exactly letter 'h' is stored (so you have pointer and constant string now.) How you can read this constant string now is with your pointer,which ofcourse can be incremented - for example in case you want to read whole word "hello" letter by letter. */

              2.)
              char t[]="hello";
              /* almost same thing happen here, but "hello" is no more constant. Its an array of characters (in another words string terminated with '\0') stored in stack. You can refer to this array by its name and ofcourse you can read/change its elements (letters) now. What you cannot do here on contrary is you cannot increment t coz it is an array now and they are like const pointers */

              There are some more differences between pointer and array.

              Comment

              • ssehgal2010
                New Member
                • Aug 2006
                • 10

                #8
                hi guys

                I tried with his example but no error in my case and also I got some strange results
                can something explain me why

                (I)
                int main(int argc, char *argv[])
                {
                char *t="hello",*r;
                r=t;
                *t='H';
                printf("%s",t);

                return(1);
                }

                result :: -> Hello

                (II)

                int main(int argc, char *argv[])
                {

                char *t="hello",*r;
                r=t;
                t="H";
                printf("%s",t);

                return(0);
                }

                result:: -> H

                can sombody explain me why?

                Comment

                • Banfa
                  Recognized Expert Expert
                  • Feb 2006
                  • 9067

                  #9
                  String constants may or may not be writable, on your system it seems that they are writable. Since this is not defined in the C standard every platform is free to do as it chooses on this point.

                  For portability it is best to assume that you can not write to string constants though.

                  As to the difference between you programs it lies in the difference between the 2 code lines

                  *t = 'H';

                  and

                  t = "H";

                  The first dereferences the pointer t so it writes the character 'H' into the memory that t already points to (in this case the string constant "Hello"), t is not changed, what t points to is changed.

                  In the second case the value of the pointer t is changed, it now points at a new memory location, at the new location is a string "H".

                  Comment

                  • jerico
                    New Member
                    • Sep 2006
                    • 39

                    #10
                    Thanks dush.Its very clear now.But I would like to know all the differences between these two:

                    char *t="hello";
                    char t[]="hello";

                    One I think is that *t can be made to point to another string but t[] can't.Bye.

                    Comment

                    • Banfa
                      Recognized Expert Expert
                      • Feb 2006
                      • 9067

                      #11
                      char *t="hello";
                      This allocates a pointer and points it at a string literal. The data pointed to should not be changed but you can change the pointer. having changed the pointer you may now be pointing at a location that is OK to write to but that depends on what you change it to. t can be easily passed by value to functions.

                      char t[]="hello";
                      This allocates an array of char just large enough to hold the string initialiser and copys the sting initialiser ("hello") into it. t is not modifiable but *t or t[N] is. You should probably pass t to functions by reference.

                      In some, but not all, instances *t and t[] are interchangeable .

                      Comment

                      • dush
                        New Member
                        • Sep 2006
                        • 27

                        #12
                        yes, you are right jerico.

                        I show you all diferences I know about on this example:

                        char *t1="hello";
                        char t2[]="hello";

                        t1 here is pointer to char value, so it can refer to any memory address and you are able to read value of char (or whole string - they end with \0) from this address. You can set pointer t1 to point anywhere because it is non constant pointer and u can read from that place. You are also allowed to write at any memory address using t1 since it is declared as pointer to non constant char (in another words you tell compiler the value pointed by t1 can be changed). But be carefull here. You should only change values at addresses that were allocated by some of your variables in stack or heap as non constant (t1 is here breaking this rule,coz it points to const string stored in data segment)

                        t2 here is array for 6 characters allocated in stack. You can think about it as it is string too. You can read and write to this array (change the string) anytime.

                        1.) difference between t1 and t2 (you already know this one) is :

                        t1 = t2; // allowed, coz t1 as I mentioned is classic pointer to char (t1 points to same place as t2 does after this assignation)

                        t2 = t1; // not allowed, coz t2 is "const pointer" and cannot point to elsewhere, but at the place of memory which was allocated for array

                        Anyway t2 behaves as pointer too. It uses arithmetic of pointers:
                        So after this assignation:
                        t1 = t2;
                        all of these are true:
                        t1 == t2;
                        t1 + 1 == t2 +1
                        *t1 == *t2
                        *(t1 + 1) == *(t2 + 1)
                        t1[1] == t2[1]

                        2. difference is:
                        sizeof(t1) != sizeof(t2)
                        // t1 is pointer and its size is 4bytes(on windows platform)
                        // t2 is array of 6 chars {'h','e','l','l ','o','\0'}
                        // 4bytes != 6bytes

                        3. difference is (after assignation t1 = t2; ):
                        t1 != &t1;
                        //this is clear to everyone
                        t2 == &t2;
                        //t2 on the left is pointer to char, &t2 on the right is pointer to array of chars and they both point at the same memory, but ofcourse different pointer arithmetic is applied for each of them:
                        t2 + 1 != &t2 +1;

                        char (*t3)[6];
                        // t3 is same type as &t2;

                        Comment

                        Working...