Understanding char*

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Norm

    Understanding char*

    Could someone explain for me what is happening here?

    char *string;
    string = new char[5];
    string = "This is the string";
    cout << string << std::endl;

    The output contains (This the string) even though I only allocated 5
    characters in memory with new.




  • Ron Natalie

    #2
    Re: Understanding char*


    "Norm" <dingoboy@myrea lbox.com> wrote in message news:bjt84m$ua9 $1@terabinaries .xmission.com.. .[color=blue]
    > Could someone explain for me what is happening here?[/color]

    char* is not a string type. It is a pointer to a single character.
    At this point in your career you should stay clear ofit. Use the std::string type instead.
    [color=blue]
    > char *string;
    > string = new char[5];[/color]

    Allocates an array of 5 char and puts the pointer to the first one in string.
    [color=blue]
    > string = "This is the string";[/color]

    You are not writing over the array of 5 you allocated above. You are assigning
    the pointer to the first character string literal (a statically allocated array of as many characters as
    needed) .

    You've essentially lost (leaked memory) the string you allocated in the previous line
    by writing over the remembered address with this one.

    And if you were to write:
    strcpy(string, "This is the string");
    which does copy the string literal over the characters pointed at by string, you'd
    be in big trouble because it's undefined behavior when you access off the end of your
    allocated memory.

    If you wanted to write the first 5 chars of a string, this is how to do it:

    #include <string>
    std::string str("This is a string");
    cout << str.substr(0,5) << "\n";



    Comment

    • Josh Lessard

      #3
      Re: Understanding char*

      > Could someone explain for me what is happening here?

      A memory leak.
      [color=blue]
      > char *string;
      > string = new char[5];[/color]

      This dynamically allocates a chunk of memory big enough to hold 5 chars,
      and returns a pointer to it (which gets stored in 'string').
      [color=blue]
      > string = "This is the string";[/color]

      This places a pointer to the character string "This is the string" in your
      variable 'string', which clobbers the old pointer value, rendering your
      previously allocated memory inaccessible.
      [color=blue]
      > The output contains (This the string) even though I only allocated 5
      > characters in memory with new.[/color]

      Yes, but you lost your pointer to that memory when you replaced it with a
      pointer to "This is the string". Remember, 'string' doesn't hold the
      allocated memory, it only holds a pointer to it.

      *************** *************** *************** ********
      Josh Lessard
      Master's Student
      School of Computer Science
      Faculty of Mathematics
      University of Waterloo
      (519)888-4567 x3400
      Waterloo's Cheriton School of Computer Science is home to world-renowned faculty committed to excellence in teaching and advancing computer science research.

      *************** *************** *************** ********

      Comment

      • Gianni Mariani

        #4
        Re: Understanding char*

        Norm wrote:[color=blue]
        > Could someone explain for me what is happening here?
        >
        > char *string;
        > string = new char[5];
        > string = "This is the string";
        > cout << string << std::endl;
        >
        > The output contains (This the string) even though I only allocated 5
        > characters in memory with new.[/color]

        "char * s" is a "pointer to char". On a x86 this is a 32 bit number
        which could theoretically address anything in memory.


        new char[5] says - go find me an unused chunk of memory in my address
        space big enout for 5 chars and "allocate it to me" and construct an
        array of 5 chars - return the pointer to the first char.

        now

        s = new char[5]

        takes the returned address and places it in s.

        "This is the string" says to the compiler, create an const char array
        and place the contents "This is the string" + a terminating ascii nul.
        The value of "This is the string" is the address of the first unsigned
        char in the array.

        so

        s = "This is the string";

        REPLACES the address returned by new char[5] in the earlier statement.

        Theoretically you have now leaked the memory from new char[5] because it
        can no longer be deleted because you no longer have the address.

        std::cout << s

        applies "ostream & operator << ( ostream &, char * )" and passes the
        address in s which happens to be "This is the string".

        .....

        Does this explain enough ?


        Comment

        • Norm

          #5
          Re: Understanding char*


          "Ron Natalie" <ron@sensor.com > wrote in message
          news:3f62261d$0 $51828$9a6e19ea @news.newshosti ng.com...[color=blue]
          >
          > "Norm" <dingoboy@myrea lbox.com> wrote in message[/color]
          news:bjt84m$ua9 $1@terabinaries .xmission.com.. .[color=blue][color=green]
          > > Could someone explain for me what is happening here?[/color]
          >
          > char* is not a string type. It is a pointer to a single character.
          > At this point in your career you should stay clear ofit. Use the[/color]
          std::string type instead.

          I know I should be using std::string instead I just trying to better
          understand c-strings and pointer concepts
          [color=blue]
          >[color=green]
          > > char *string;
          > > string = new char[5];[/color]
          >
          > Allocates an array of 5 char and puts the pointer to the first one in[/color]
          string.[color=blue]
          >[color=green]
          > > string = "This is the string";[/color]
          >
          > You are not writing over the array of 5 you allocated above. You are[/color]
          assigning[color=blue]
          > the pointer to the first character string literal (a statically allocated[/color]
          array of as many characters as[color=blue]
          > needed) .
          >
          > You've essentially lost (leaked memory) the string you allocated in the[/color]
          previous line[color=blue]
          > by writing over the remembered address with this one.
          >
          > And if you were to write:
          > strcpy(string, "This is the string");
          > which does copy the string literal over the characters pointed at by[/color]
          string, you'd[color=blue]
          > be in big trouble because it's undefined behavior when you access off the[/color]
          end of your[color=blue]
          > allocated memory.[/color]

          Just so I understand if I were to write this:

          char *string;
          string = new char[5];
          strcpy(string, "This is the string");

          It does copy to the the string to the allocated char's by new correct? But
          in this example since the string does not fit I am getting an undefined
          behavior? In my simple example what is being done with the extra char's that
          don't fit? Is my compiler just seeing this and trying to fix the problem?
          Because when I do (std::cout << string) the output is the entire string
          literal.

          Here is another question to clarify this concept for me. If I were to do
          this:

          char *string;
          string = new char[50];
          strcpy(string, "This is the string");
          std::cout << string;
          strcpy(string, "This is another string");
          std::cout << string;

          I am assuming the second strcpy is starting over from the begging and
          overwriting everything from the first strcpy. Would it have been better to
          delete and reallocate memory for the new string?

          char *string;
          string = new char[50];
          strcpy(string, "This is the string");
          std::cout << string;
          delete string;
          string = new char[50];
          strcpy(string, "This is another string");
          std::cout << string;

          Thanks for the help everyone!
          [color=blue]
          >
          > If you wanted to write the first 5 chars of a string, this is how to do[/color]
          it:[color=blue]
          >
          > #include <string>
          > std::string str("This is a string");
          > cout << str.substr(0,5) << "\n";
          >
          >
          >[/color]


          Comment

          • Ron Natalie

            #6
            Re: Understanding char*


            "Norm" <dingoboy@myrea lbox.com> wrote in message news:bjtb6c$uug $1@terabinaries .xmission.com.. .[color=blue]
            >
            > It does copy to the the string to the allocated char's by new correct?[/color]

            Yes, strcpy is logically:
            char* strcpy(char* to, const char* from) {
            char* ret = to;
            while(*to++ = *from++);
            return ret;
            }

            [color=blue]
            > But
            > in this example since the string does not fit I am getting an undefined
            > behavior?[/color]

            Yes, as soon as strcpy attempts to write the string[5] it is undefined
            behavior.
            [color=blue]
            > In my simple example what is being done with the extra char's that
            > don't fit?[/color]

            It attempts to write them in string[5], string[6]... but that's not a defined
            operation since those locations have not been allocated.
            [color=blue]
            > Is my compiler just seeing this and trying to fix the problem?
            > Because when I do (std::cout << string) the output is the entire string
            > literal.[/color]

            The compiler doesn't know or care. That's the problem with undefined
            behavior. It may or may not work at run time. If it printed it, you just
            got lucky and the extra characters you wrote didn't hit anything.

            All the str* functions and anything that treats char* as if it were a string
            just starts marching through memory from the given pointer looking
            for the first null character.

            [color=blue]
            > Here is another question to clarify this concept for me. If I were to do
            > this:
            >
            > char *string;
            > string = new char[50];
            > strcpy(string, "This is the string");
            > std::cout << string;
            > strcpy(string, "This is another string");
            > std::cout << string;
            >
            > I am assuming the second strcpy is starting over from the begging and
            > overwriting everything from the first strcpy. Would it have been better to
            > delete and reallocate memory for the new string?[/color]

            No.... As long as you don't run off the 50 characters.
            You don't even need to new anything, C++ is not JAVA.
            char string[50];
            would have worked just fine and you never have to remember to
            delete it.

            If you had used std::string, you wouldn't have to worry about running off
            the end, and assignment would work as you expect.
            [color=blue]
            > delete string;[/color]

            BZZT. More undefined behavior. Anything you allocate with the array form of new
            you need to deallocate with the array form of delete.

            delete [] string;
            [color=blue]
            > string = new char[50];
            > strcpy(string, "This is another string");
            > std::cout << string;[/color]

            Don't forget that you need to delete string here if you are done with it.


            Comment

            • Artie Gold

              #7
              Re: Understanding char*

              Norm wrote:[color=blue]
              > "Ron Natalie" <ron@sensor.com > wrote in message
              > news:3f62261d$0 $51828$9a6e19ea @news.newshosti ng.com...
              >[color=green]
              >>"Norm" <dingoboy@myrea lbox.com> wrote in message[/color]
              >
              > news:bjt84m$ua9 $1@terabinaries .xmission.com.. .
              >[color=green][color=darkred]
              >>>Could someone explain for me what is happening here?[/color]
              >>
              >>char* is not a string type. It is a pointer to a single character.
              >>At this point in your career you should stay clear ofit. Use the[/color]
              >
              > std::string type instead.
              >
              > I know I should be using std::string instead I just trying to better
              > understand c-strings and pointer concepts
              >
              >[color=green][color=darkred]
              >>>char *string;
              >>>string = new char[5];[/color]
              >>
              >>Allocates an array of 5 char and puts the pointer to the first one in[/color]
              >
              > string.
              >[color=green][color=darkred]
              >>>string = "This is the string";[/color]
              >>
              >>You are not writing over the array of 5 you allocated above. You are[/color]
              >
              > assigning
              >[color=green]
              >>the pointer to the first character string literal (a statically allocated[/color]
              >
              > array of as many characters as
              >[color=green]
              >>needed) .
              >>
              >>You've essentially lost (leaked memory) the string you allocated in the[/color]
              >
              > previous line
              >[color=green]
              >>by writing over the remembered address with this one.
              >>
              >>And if you were to write:
              >> strcpy(string, "This is the string");
              >>which does copy the string literal over the characters pointed at by[/color]
              >
              > string, you'd
              >[color=green]
              >>be in big trouble because it's undefined behavior when you access off the[/color]
              >
              > end of your
              >[color=green]
              >>allocated memory.[/color]
              >
              >
              > Just so I understand if I were to write this:
              >
              > char *string;
              > string = new char[5];
              > strcpy(string, "This is the string");
              >
              > It does copy to the the string to the allocated char's by new correct? But
              > in this example since the string does not fit I am getting an undefined
              > behavior? In my simple example what is being done with the extra char's that
              > don't fit? Is my compiler just seeing this and trying to fix the problem?
              > Because when I do (std::cout << string) the output is the entire string
              > literal.[/color]

              Right. You're getting undefined behavior. In this case, you just
              happened to get unlucky, and it *seemed* to work correctly.[1]
              [color=blue]
              >
              > Here is another question to clarify this concept for me. If I were to do
              > this:
              >
              > char *string;
              > string = new char[50];
              > strcpy(string, "This is the string");
              > std::cout << string;
              > strcpy(string, "This is another string");
              > std::cout << string;
              >
              > I am assuming the second strcpy is starting over from the begging and
              > overwriting everything from the first strcpy. Would it have been better to
              > delete and reallocate memory for the new string?[/color]

              Not at all. You allocated space for 50 `char's. It's yours. You may
              do what you want with it (but be sure to delete it when you no
              longer need it).
              [color=blue]
              >
              > char *string;
              > string = new char[50];
              > strcpy(string, "This is the string");
              > std::cout << string;
              > delete string;
              > string = new char[50];
              > strcpy(string, "This is another string");
              > std::cout << string;[/color]

              Not necessary.
              [color=blue][color=green]
              >>If you wanted to write the first 5 chars of a string, this is how to do[/color]
              >
              > it:
              >[color=green]
              >>#include <string>
              >>std::string str("This is a string");
              >>cout << str.substr(0,5) << "\n";
              >>
              >>
              >>[/color]
              >
              >
              >[/color]
              HTH,
              --ag

              [1] The reason *seeming* to work is an unlucky occurence is that,
              particularly with buffer overrun kinds of problems, you're likely to
              have overwritten a piece of memory that will result in a crash in
              some other part of your program. Situations like that tend to be
              devilishly difficult to track down.
              --
              Artie Gold -- Austin, Texas

              Comment

              • Ying Yang

                #8
                Re: Understanding char*

                [color=blue]
                > Could someone explain for me what is happening here?
                >
                > char *string;[/color]

                You have declared a pointer named string to a char type. This pointer is
                allocated on the stack.
                [color=blue]
                > string = new char[5];[/color]

                You have made this pointer point to the first element in a constant array of
                type char that has 5 elements. This constant array is allocated on the heap
                (using the new operator). Note, there is a close association between
                pointers and arrays.
                [color=blue]
                > string = "This is the string";
                > cout << string << std::endl;
                > The output contains (This the string) even though I only allocated 5
                > characters in memory with new.[/color]

                The elements in the constant array is filled with the characters in the
                string literal. Two important things to notice here is that (1) the null
                character is automatically appended at the end of the array (2) it is
                possible to over-write next memory locations as C++ does not do run-time
                checks for array indexes that go out of bounds.

                Hope this helps.

                weeeeeeeeeeee



                ---
                Outgoing mail is certified Virus Free.
                Checked by AVG anti-virus system (http://www.grisoft.com).
                Version: 6.0.510 / Virus Database: 307 - Release Date: 14/08/2003


                Comment

                • Steven C.

                  #9
                  Re: Understanding char*

                  This is a very good explaination.


                  "Gianni Mariani" <gi2nospam@mari ani.ws> wrote in message
                  news:bjt93m$op0 @dispatch.conce ntric.net...
                  Norm wrote:[color=blue]
                  > Could someone explain for me what is happening here?
                  >
                  > char *string;
                  > string = new char[5];
                  > string = "This is the string";
                  > cout << string << std::endl;
                  >
                  > The output contains (This the string) even though I only allocated 5
                  > characters in memory with new.[/color]

                  "char * s" is a "pointer to char". On a x86 this is a 32 bit number
                  which could theoretically address anything in memory.


                  new char[5] says - go find me an unused chunk of memory in my address
                  space big enout for 5 chars and "allocate it to me" and construct an
                  array of 5 chars - return the pointer to the first char.

                  now

                  s = new char[5]

                  takes the returned address and places it in s.

                  "This is the string" says to the compiler, create an const char array
                  and place the contents "This is the string" + a terminating ascii nul.
                  The value of "This is the string" is the address of the first unsigned
                  char in the array.

                  so

                  s = "This is the string";

                  REPLACES the address returned by new char[5] in the earlier statement.

                  Theoretically you have now leaked the memory from new char[5] because it
                  can no longer be deleted because you no longer have the address.

                  std::cout << s

                  applies "ostream & operator << ( ostream &, char * )" and passes the
                  address in s which happens to be "This is the string".

                  .....

                  Does this explain enough ?



                  Comment

                  • Big Brian

                    #10
                    Re: Understanding char*

                    > > Could someone explain for me what is happening here?[color=blue]
                    >
                    > char* is not a string type. It is a pointer to a single character.
                    > At this point in your career you should stay clear ofit. Use the std::string type instead.[/color]

                    Everybody needs to understand c style strings as well. I've worked on
                    projects where you couldn't use std::string. And you never know when
                    you're going to have to maintain old code which uses them.

                    Comment

                    • Jakob Bieling

                      #11
                      Re: Understanding char*

                      "Ying Yang" <YingYang@hotma il.com> wrote in message
                      news:3f627ddb$1 _1@news.iprimus .com.au...
                      [color=blue][color=green]
                      > > string = new char[5];[/color]
                      >
                      > You have made this pointer point to the first element in a constant array[/color]
                      of[color=blue]
                      > type char that has 5 elements. This constant array is allocated on the[/color]
                      heap[color=blue]
                      > (using the new operator). Note, there is a close association between
                      > pointers and arrays.[/color]

                      Why are you saying 'constant array'? The array of chars that is
                      allocated by the statement above is not constant at all.
                      [color=blue][color=green]
                      > > string = "This is the string";
                      > > cout << string << std::endl;
                      > > The output contains (This the string) even though I only allocated 5
                      > > characters in memory with new.[/color]
                      >
                      > The elements in the constant array is filled with the characters in the
                      > string literal.[/color]

                      No, not at all. The elements of the array you allocated with 'new[]' are
                      untouched and the pointer to the first element of that array is lost. See
                      Gianni's post for an in-depth explanation.
                      [color=blue]
                      > Two important things to notice here is that (1) the null
                      > character is automatically appended at the end of the array[/color]

                      Using the above statement, no. This applies when using any of the str*
                      functions, like strcpy, strcat and whatnot.

                      regards
                      --
                      jb

                      (replace y with x if you want to reply by e-mail)


                      Comment

                      • John Carson

                        #12
                        Re: Understanding char*

                        "Norm" <dingoboy@myrea lbox.com> wrote in message
                        news:bjtb6c$uug $1@terabinaries .xmission.com[color=blue]
                        >
                        > Just so I understand if I were to write this:
                        >
                        > char *string;
                        > string = new char[5];
                        > strcpy(string, "This is the string");
                        >
                        > It does copy to the the string to the allocated char's by new
                        > correct? But in this example since the string does not fit I am
                        > getting an undefined behavior? In my simple example what is being
                        > done with the extra char's that don't fit? Is my compiler just seeing
                        > this and trying to fix the problem? Because when I do (std::cout <<
                        > string) the output is the entire string literal.[/color]

                        The point is that there are two memory allocation mechanisms available and
                        you are assuming that there is only one, name that provided by new.

                        You could write:

                        char *string;
                        string = "This is the string";
                        cout << string << std::endl;

                        without any use of new and it would be fine. The compiler will put "This is
                        the string" in statically allocated memory, i.e., memory reserved when the
                        program first starts up. It then makes the string variable point to the
                        start of this statically allocated memory. Statically allocated memory is
                        the same as what you get if, say, you write

                        int x;

                        at global scope.
                        [color=blue]
                        > Here is another question to clarify this concept for me. If I were to
                        > do this:
                        >
                        > char *string;
                        > string = new char[50];
                        > strcpy(string, "This is the string");
                        > std::cout << string;
                        > strcpy(string, "This is another string");
                        > std::cout << string;
                        >
                        > I am assuming the second strcpy is starting over from the begging and
                        > overwriting everything from the first strcpy. Would it have been
                        > better to delete and reallocate memory for the new string?[/color]

                        No, that just makes extra work for no gain.



                        --
                        John Carson
                        1. To reply to email address, remove donald
                        2. Don't reply to email address (post here instead)

                        Comment

                        • Jakob Bieling

                          #13
                          Re: Understanding char*

                          "John Carson" <donaldquixote@ datafast.net.au > wrote in message
                          news:3f6307db_2 @news.brisbane. pipenetworks.co m...[color=blue]
                          > "Norm" <dingoboy@myrea lbox.com> wrote in message
                          > news:bjtb6c$uug $1@terabinaries .xmission.com[color=green]
                          > >
                          > > Just so I understand if I were to write this:
                          > >
                          > > char *string;
                          > > string = new char[5];
                          > > strcpy(string, "This is the string");
                          > >
                          > > It does copy to the the string to the allocated char's by new
                          > > correct? But in this example since the string does not fit I am
                          > > getting an undefined behavior? In my simple example what is being
                          > > done with the extra char's that don't fit? Is my compiler just seeing
                          > > this and trying to fix the problem? Because when I do (std::cout <<
                          > > string) the output is the entire string literal.[/color]
                          >
                          > The point is that there are two memory allocation mechanisms available and
                          > you are assuming that there is only one, name that provided by new.
                          >
                          > You could write:
                          >
                          > char *string;
                          > string = "This is the string";
                          > cout << string << std::endl;
                          >
                          > without any use of new and it would be fine. The compiler will put "This[/color]
                          is[color=blue]
                          > the string" in statically allocated memory, i.e., memory reserved when the
                          > program first starts up. It then makes the string variable point to the
                          > start of this statically allocated memory.[/color]

                          You should note that memory allocated like this is constant, meaning
                          that you may not change it. I do not remember why the following compiles:

                          char* tyt = "hello world";
                          tyt [0] = 'H';

                          but when running it, it will give you an access violation. IMO, the
                          string literal should be of type 'char const*', but for some reason it seems
                          not to be.

                          regards
                          --
                          jb

                          (replace y with x if you want to reply by e-mail)


                          Comment

                          • Kevin Goodsell

                            #14
                            Re: Understanding char*

                            Jakob Bieling wrote:
                            [color=blue]
                            >
                            >
                            > You should note that memory allocated like this is constant, meaning
                            > that you may not change it. I do not remember why the following compiles:
                            >
                            > char* tyt = "hello world";
                            > tyt [0] = 'H';[/color]

                            Basically it's for historical reasons. C allowed literals to be modified
                            way back in the day. Implicit conversion of a string literal to a
                            (non-const) char * is deprecated in C++. You should always use const
                            char * for this purpose.
                            [color=blue]
                            >
                            > but when running it, it will give you an access violation. IMO, the
                            > string literal should be of type 'char const*', but for some reason it seems
                            > not to be.[/color]

                            Actually, the type of a string literal is const char[N] where N is the
                            number of characters including the null terminator. So it *is* const,
                            but it's a special case with that implicit conversion.

                            -Kevin
                            --
                            My email address is valid, but changes periodically.
                            To contact me please use the address from a recent posting.

                            Comment

                            • Gianni Mariani

                              #15
                              Re: Understanding char*

                              Jakob Bieling wrote:[color=blue]
                              > "John Carson" <donaldquixote@ datafast.net.au > wrote in message
                              > news:3f6307db_2 @news.brisbane. pipenetworks.co m...
                              >[/color]
                              [color=blue]
                              >
                              > You should note that memory allocated like this is constant, meaning
                              > that you may not change it. I do not remember why the following compiles:
                              >
                              > char* tyt = "hello world";
                              > tyt [0] = 'H';
                              >
                              > but when running it, it will give you an access violation. IMO, the
                              > string literal should be of type 'char const*', but for some reason it seems
                              > not to be.[/color]

                              It may or may not fault - it's undefined.

                              The reason why tyt does not need to be a "const char *" is there is a
                              special C++ rule for conversion of a string literal to a "char *" to
                              deal with all the bad code out there.

                              Comment

                              Working...