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

D

David Pratt

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.
 
S

Steven T. Hatton

David said:
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:

I sure looks like C to me.
#include <Stdlib.h>

//---------------------------------------------------------------
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.

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.
 
N

Noah Roberts

David said:
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;


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.
 
D

David Pratt

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.
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.
 
P

peter koch

David Pratt skrev:
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.

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
 
K

kwikius

David said:
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.

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
 
N

Noah Roberts

David said:
Ah but if I had done that, I would still be operating under false
assumptions about the way C++ handles pointers.

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

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.

Well, here...something to digest then:

while (*ptr1++ = *ptr2++);
 
H

Howard

David Pratt said:
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:

(Ok. I'll avoid the obvious comments about using std::string, since you're
interested in arrays only here.)
#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

Why malloc? Why not new[]?
char T2[20] = "Hello World!";

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.
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


That's not "by reference". By reference means using &. You're passing via
a pointer.
"Not Hello World"
---------------------------------------------------------------*/
{
char* T2 = "Not Hello World\0";

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


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


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.
//---------------------------------------------------------------
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

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.
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.

Me, too. Now you just need to follow the advice given. ;-)

-Howard
 
O

Old Wolf

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

"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.
 
A

Alf P. Steinbach

* Old Wolf:
"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.

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.
 
D

David Pratt

Well, here...something to digest then:

while (*ptr1++ = *ptr2++);
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.
 
S

Steven T. Hatton

David said:
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.

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>
 
S

Steven T. Hatton

Alf said:
* 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.

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."
 
F

F.J.K.

David said:
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.

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
 
S

Steven T. Hatton

F.J.K. said:
David Pratt schrieb:
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:

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.
 
N

Noah Roberts

David said:
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.

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.
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.

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.
 

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. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top