Ok, I was in error (or my foot still doesn't taste so great)

Discussion in 'C++' started by David Pratt, Dec 13, 2006.

  1. David Pratt

    David Pratt Guest

    I recently replied to MC felons post on returning strings and was in error
    on what I was trying to do. After running completely thru my code, I did
    find that I was misunderstanding how C++ works with char arrays. After much
    testing, I would like to submit the following code for comments:

    #include <Stdlib.h>

    char *Func1()
    /*-------------------------------------------------------------------
    allocates memory and fills it with the string, "Hello World!" and
    passes ownership to the calling function
    ---------------------------------------------------------------------*/
    {
    char *tmp = (char*)malloc(20); // allocate space for the array
    char T2[20] = "Hello World!";
    int i = 0;

    // fill the char array
    do
    {
    tmp = T2;
    i++;
    }while(T2 != 0);
    tmp = 0;
    return tmp;
    };

    //---------------------------------------------------------------
    void Func2(char *tmp)
    /*--------------------------------------------------------------
    Takes a string argument by reference and changes it to
    "Not Hello World"
    ---------------------------------------------------------------*/
    {
    char* T2 = "Not Hello World\0";

    int i=0;
    do
    {
    tmp = T2;
    i++;
    }while(T2!=0);
    tmp=0;
    };

    //---------------------------------------------------------------
    int main()
    {
    char *Tmp = Func1(); // allocates memory for array and fills it with "Hello
    World"
    Func2(Tmp); // change string to "Not Hello World!"
    free(Tmp); // free memory allocated in Func1 and assigned
    to Tmp;
    };

    In all my test runs, I get the desired results without any errors. While I
    acknowledge that using the string functions would be preferable, I still
    like to code my own solutions sometimes just for the learning experience.
     
    David Pratt, Dec 13, 2006
    #1
    1. Advertisements

  2. I sure looks like C to me.
    Why not and have a look at the GNU implementation of <string.h>?

    BTW, there were two primary reasons I didn't like C. One was malloc, and
    the other was free.
     
    Steven T. Hatton, Dec 13, 2006
    #2
    1. Advertisements

  3. David Pratt

    Noah Roberts Guest



    Why reinvent the wheel? You could have just done this whole loop with
    strcpy and it's all a whole lot more work than using std::string.
     
    Noah Roberts, Dec 13, 2006
    #3
  4. David Pratt

    David Pratt Guest

    Ah but if I had done that, I would still be operating under false
    assumptions about the way C++ handles pointers. Now I KNOW better. What can
    I say? I was an engineering student in college, and I have this ever present
    itch to try and figure out how things work, especially when what I thought
    would work doesn't. I learned a lot over the past couple of days about C++
    basics. And trying to reinvent the wheel got us tracked vehicles.

    "Sometimes learning what you don't know that you don't know can be more
    important than learning about what you know that you don't know." Wener
    Earhart, founder of est.
     
    David Pratt, Dec 13, 2006
    #4
  5. David Pratt

    peter koch Guest

    David Pratt skrev:
    This is just perfectly fine. Now go forget all that knowledge and start
    using std::string instead. I believe you realise that while your code
    did work well in your test, simple changes could have changed that
    (e.g. mallocing somewhat less than 20 bytes.
    std::string should be preferred at all times unless you have very good
    argument to use something different.

    /Peter
     
    peter koch, Dec 13, 2006
    #5
  6. David Pratt

    kwikius Guest

    FWIW I agree with you absolutely. (I would ignore all those other
    miserable old people on this newsgroup and experiment). Bear in mind
    though that the standard libraries are the result of a huge amount of
    work, not only in the coding but also in the documentation, which means
    that for serious work it is usually easier to use them. However its
    only when you try to do it yourself that you appreciate that IMO. And
    of course you may also come up with something better too someday..

    regards
    Andy Little
     
    kwikius, Dec 13, 2006
    #6
  7. David Pratt

    Noah Roberts Guest

    Well, you learned how null terminated character strings work possibly.
    It isn't quite the same thing.

    Now I KNOW better. What can
    Well, here...something to digest then:

    while (*ptr1++ = *ptr2++);
     
    Noah Roberts, Dec 13, 2006
    #7
  8. David Pratt

    Howard Guest

    (Ok. I'll avoid the obvious comments about using std::string, since you're
    interested in arrays only here.)
    Why malloc? Why not new[]?
    You're making the array of size 20 because Func2 is going to add data to it.
    It's bad design to specify a value in one function that's only needed by
    some other function. If you've got a "global" requirement like this, it's
    better to put the value (20) in a global constant, and use that constant
    when allocating.


    That's not "by reference". By reference means using &. You're passing via
    a pointer.


    What if T2[0]==0? Better to use a for loop here.


    There is nothing in that function which tells you if it's safe to write to a
    given location in the array. It's got no way to know that in some other
    function (Func1), this pointer was allocated as an array of 20 chars. What
    if you change Func1 to allocate only 12 chars?

    Using this design, it would be much better if you added another parameter to
    Func2 which would tell it how big the array is, so you could stop writing
    before you got to its end. Or, if you followed my earlier advice and put
    the value 20 into a global constant, you could use that as a safety check.
    Better to use new[] and delete[] in C++, especially if you decide to extend
    this type of code to an array of objects. Using new[] and delete[], the
    constructors and destructors for those objects will be called. Not so for
    malloc/free.
    Me, too. Now you just need to follow the advice given. ;-)

    -Howard
     
    Howard, Dec 13, 2006
    #8
  9. David Pratt

    Old Wolf Guest

    "By reference" means that the function refers to a value that
    exists outside of it. There are two ways to do this in C++:
    pointers and references.
     
    Old Wolf, Dec 13, 2006
    #9
  10. * Old Wolf:
    In a sense you're right. A design model with some argument passed by
    reference, might be implemented in C++ as a C++ alias, a pointer, or
    even an array index. But in the context of the C++ language "pass by
    reference" means &: all else is pass by value.
     
    Alf P. Steinbach, Dec 13, 2006
    #10
  11. David Pratt

    David Pratt Guest

    I am assuming that ptr1 and ptr are both char Array pointers.

    Well, I do not know if it's just my compiler or what, but the assembly code
    generated by the above code will allways evaluate true, resulting in an
    endless loop that overwrites all the memory after ptr2 with the contents
    after ptr1. But might you mean:
    while(*ptr1++ == *ptr2++);
    If so then you have undeterminate results if both arrays are equal strings
    because the bytes past the end of the arrays are not guaranteed to be
    unequal. The expression might or might not evaluate to false after the ends
    of each array are reached.
     
    David Pratt, Dec 14, 2006
    #11
  12. if ptr2 is a NTBS, *ptr1++ = *ptr2++ should get to *ptr2=='\0'. That should
    terminate the loop because you are assigning *ptr1='\0' which
    returns '\0', and should evaluate to false.


    This is verbatim from pg 106 of K&R.
    <quote>
    void strcpy(char *s, char *t)
    {
    while(*s++ = *t++)
    ;
    }
    Although this may seem cryptic at first sight, the notational convenience is
    considerable, and the idiom should be mastered, because you will see it
    frequently in C programs.
    </quote>
     
    Steven T. Hatton, Dec 14, 2006
    #12
  13. http://www.parashift.com/c++-faq-lite/value-vs-ref-semantics.html

    http://publib.boulder.ibm.com/infoc.../com.ibm.xlcpp8a.doc/language/ref/cplr233.htm

    "Pass by reference

    Passing by by reference refers to a method of passing the address of an
    argument in the calling function to a corresponding parameter in the called
    function. C onlyIn C, the corresponding parameter in the called function
    must be declared as a pointer type. C++ only In C++, the corresponding
    parameter can be declared as any reference type, not just a pointer type."
     
    Steven T. Hatton, Dec 14, 2006
    #13
  14. David Pratt

    F.J.K. Guest

    Well, as it seems you like citations. Here is one, dedicated to you
    personally.

    "Sometimes it is good to read a book. You should read one book in your
    life, better would be two or even three." F.J.K., wizard of Oz.

    Honestly, if you are interested in a C-like programming style, read the
    K.&.R. You'll be amazed at how much you can learn in how little time,
    by listening to smart people. After all, you don't want to be cited by
    your successors with:

    "If I haven't seen further than others, it's because I refused standing
    on the shoulders of giants and had to reinvent and refine strcpy all by
    myself 'without cheating'." David Pratt, founder of nothing
     
    F.J.K., Dec 14, 2006
    #14
  15. I'll refrain from the personal jabs. I do agree, however, that K&R seems
    like a good source for David to consult. I keep pulling it off the shelf
    wishing I had time to read it again myself.
     
    Steven T. Hatton, Dec 14, 2006
    #15
  16. David Pratt

    Noah Roberts Guest

    Examine the expression. The first thing to take place is the
    incrementing of the pointers and the result of that is the original
    value. Second is the dereference of the original value. Third the
    value of the rvalue is assigned to the lvalue location. Finally the
    data that was copied is the result of the expression. Assuming we have
    a null terminated string the last data value of ptr2 will be a 0 and
    thus ending the loop...after it is copied into ptr1.

    It's strcpy.
    Correct, that will not do the same thing as the result of == is either
    true/false based on the sameness of l and r operands...'\0' won't
    terminate the loop in this case.
     
    Noah Roberts, Dec 14, 2006
    #16
    1. Advertisements

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.