By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
449,315 Members | 1,672 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 449,315 IT Pros & Developers. It's quick & easy.

Another Understanding Pointers Question

P: n/a
Hi everyone,
I seen the post by Rob Morris, and thought that I would double check
that I was using pointers in the correct way. So I written the following
string functions to test. I know soem can be iumplimented using the
standard libary, but I just wanted to test writing my own functions.
They work ok, but I would like some feed back on any issues you can see
with them etc

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char *left(char *string, int count)
{
char *p;
int i;
p = malloc((count * sizeof(char)+1));
if(!p){
printf("Cannot allocate memory\n");
exit(1);
}
for(i = 0; i <= count -1; i++) {
p[i] = string[i];
}
p[i++] = '\0';

return(p);

}

char *right(char *string, int count)
{
char *p;
int len, i, j = 0;
p = malloc((count * sizeof(char)+1));
if(!p){
printf("Cannot allocate memory\n");
exit(1);
}
len = strlen(string);
for(i = (len - count); i <= len; i++){
p[j] = string[i];
j++;
}

p[j++] = '\0';
return(p);

}

char *chreplace(char *string, int count, char rep)
{
char *p;
p = malloc((sizeof(string)+1));
if(!p){
printf("Cannot allocate memory\n");
exit(1);
}
count--;
strcpy(p, string);
p[count] = rep;

return(p);
}

char *section(char *string, int from, int to)
{
char *p;
int i, j = 0;

p = malloc(((to - from) * sizeof(char)+1));
if(!p){
printf("Cannot allocate memory\n");
exit(1);
}
for( i = from; i <= to; i++) {
p[j] = string[i];
j++;
}
p[j++] = '\0';

return(p);
}
int main(void)
{
char blah[] = "abcdefghijklm";
char *test;
char *test2;
char *test3;
char *test4;

test = left(blah, 10);
test2 = right(blah, 10);
test3 = chreplace(blah, 2, 'Q');
test4 = section(blah, 4, 10);
puts(test);
puts(test2);
puts(test3);
puts(test4);
return 0;
}

Comments and improvements are welcome, flames to if appropriate.
--
------
Materialised

perl -e 'printf "%silto%c%sck%ccodegurus%corg%c", "ma", 58, "mi", 64,
46, 10;'
Nov 14 '05 #1
Share this Question
Share on Google+
26 Replies


P: n/a
On Mon, 10 May 2004 15:11:42 +0100, Materialised <Ma**********@privacy.net>
wrote:
Hi everyone,
I seen the post by Rob Morris, and thought that I would double check
that I was using pointers in the correct way. So I written the following
string functions to test. I know soem can be iumplimented using the
standard libary, but I just wanted to test writing my own functions.
They work ok, but I would like some feed back on any issues you can see
with them etc
Okay, I'll point out some things I see. I'm sure there's much else others
will catch.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char *left(char *string, int count)
Since you're not modifying string, define it as pointer-to-const:

char *left(const char *string, int count)
(or, Dan Saks style)
char *left(char const *string, int count)

{
char *p;
int i;
p = malloc((count * sizeof(char)+1));
I don't know if there's a group consensus or not on whether it is worth the
trouble to say 'sizeof(char)' when the value is always 1. Personally, I'd
leave it out for the sake of simplicity:
p = malloc(count + 1);

Except for one thing: you don't know if you'll need all of that space.
What if someone specifies count as 10000? Wouldn't you be better of
figuring out, first, how much space you're /really/ going to need and just
allocating that?
if(!p){
printf("Cannot allocate memory\n");
exit(1);
}
for(i = 0; i <= count -1; i++) {
p[i] = string[i];
Another problem if count is too big is you'll keep going right off the end
of the source array here (undefined behavior).
}
p[i++] = '\0';

return(p);

}

char *right(char *string, int count)
All the same issues as above (well, now if count is too big you'll be
trying to read out of memory /before/ string instead of after it...)
{
char *p;
int len, i, j = 0;
p = malloc((count * sizeof(char)+1));
if(!p){
printf("Cannot allocate memory\n");
exit(1);
}
len = strlen(string);
for(i = (len - count); i <= len; i++){
p[j] = string[i];
j++;
}

p[j++] = '\0';
return(p);

}

char *chreplace(char *string, int count, char rep) blah blah const blah blah...{
char *p;
p = malloc((sizeof(string)+1));
if(!p){
printf("Cannot allocate memory\n");
exit(1);
}
count--;
strcpy(p, string);
p[count] = rep; No sanity checking on count (again).
return(p); don't need parens there. return is not a function.
}

char *section(char *string, int from, int to) const,
sanity checking of from/to
{
char *p;
int i, j = 0;

p = malloc(((to - from) * sizeof(char)+1));
if(!p){
printf("Cannot allocate memory\n");
exit(1);
}
for( i = from; i <= to; i++) {
p[j] = string[i];
j++;
}
p[j++] = '\0';

return(p);
}
int main(void)
{
char blah[] = "abcdefghijklm";
char *test;
char *test2;
char *test3;
char *test4;

test = left(blah, 10);
test2 = right(blah, 10);
test3 = chreplace(blah, 2, 'Q');
test4 = section(blah, 4, 10);
puts(test);
puts(test2);
puts(test3);
puts(test4);
return 0;
}

Comments and improvements are welcome, flames to if appropriate.


That should give you a bit to work on...
-leor
--
Leor Zolman --- BD Software --- www.bdsoft.com
On-Site Training in C/C++, Java, Perl and Unix
C++ users: download BD Software's free STL Error Message Decryptor at:
www.bdsoft.com/tools/stlfilt.html
Nov 14 '05 #2

P: n/a
On Mon, 10 May 2004, Materialised wrote:
Hi everyone,
I seen the post by Rob Morris, and thought that I would double check
that I was using pointers in the correct way. So I written the following
string functions to test. I know soem can be iumplimented using the
standard libary, but I just wanted to test writing my own functions.
They work ok, but I would like some feed back on any issues you can see
with them etc

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char *left(char *string, int count)
{
char *p;
int i;
It is a good habit to check your inputs. What if string == NULL? what if
count > strlen(string)? You can actually check this as you copy the string
over to p.
p = malloc((count * sizeof(char)+1));
The value of sizeof(char) is always 1. This can be simplified to:

p = malloc(count+1);
if(!p){
printf("Cannot allocate memory\n");
exit(1);
}
I would be less likely to use a function that exits on failure. You have
taken away all control from the calling function. What if I had created a
lot of data then called your function? I'd be very annoyed to lose all
that data. If you returned NULL instead then I have the option to
continue, save and quit or just quit.
for(i = 0; i <= count -1; i++) {
I just like to see:

for(i = 0; i < count; i++) {

it seems more natural. Additionally, what if count > strlen(string)? The
p[i] is safe but is the string[i]?
p[i] = string[i];
}
p[i++] = '\0';
Why increment i? This could have just as easily been:

p[i] = '\0';
return(p);
}
As far as pointer usage goes, this to good. Some comments on the code
would be good. When I saw the count+1 in the malloc I was wondering why
the +1. I assumed it was for the null character but without comments I
couldn't be sure. As someone using your function I'd have to read and
understand the code to be sure I was using it correctly. Having a
commented at the top explaining usage would be good.
char *right(char *string, int count)
{
char *p;
int len, i, j = 0;
Same as previous function. Check your inputs.
p = malloc((count * sizeof(char)+1));
Same as previous function.
if(!p){
printf("Cannot allocate memory\n");
exit(1);
}
Same as previous function.
len = strlen(string);
for(i = (len - count); i <= len; i++){
p[j] = string[i];
j++;
}
Good. Might be better using:

for(j = 0; i = (len - count); j < count; i++, j++)
p[j] = string[i];

First, I initialize j here. This way I'm sure I initialized it and no code
between the top of the function and here changed it.

Second, using the j index to exit the loop just seems right to me. This is
just a personal preference though.

Third, use the comma operator and make the code a little shorter. I like
to put as much on one screen as I can without losing readability.

Finally, we are sure that p[j] is safe. What about string[i]? You might
have an array out of bounds there as well.
p[j++] = '\0';
Again, why increment j?
return(p);
}
All-in-all, a good use of pointers.
char *chreplace(char *string, int count, char rep)
{
char *p;
Check the inputs.
p = malloc((sizeof(string)+1));
First serious mistake. The sizeof(string) will be the sizeof(char*). You
don't want the size of a pointer. You want the size of the string being
pointed to. This should be:

p = malloc(strlen(string)+1);
if(!p){
printf("Cannot allocate memory\n");
exit(1);
}
Same thing as previous functions.
count--;
Not immediately obvious why you are decrementing count. I can read your
code and figure out that the count parameter is 1-indexed and you are
decrementing it to make it 0-indexed but I should have to read your code
to figure that out.
strcpy(p, string);
p[count] = rep;
You could actually combine two lines and have:

p[--count] = rep;
return(p);
}
I like the fact that even of the user passing a literal string this
function still works.
char *section(char *string, int from, int to)
{
char *p;
int i, j = 0;
Check the inputs.
p = malloc(((to - from) * sizeof(char)+1));
The sizeof(char) is redundant. What if to-from < 0? It could happen. Check
the inputs.
if(!p){
printf("Cannot allocate memory\n");
exit(1);
}
Same as previous functions.
for( i = from; i <= to; i++) {
p[j] = string[i];
j++;
}
for(j = 0, i = from; i <= to; i++, j++)
p[j] = string[i];
p[j++] = '\0';
Why increment j?
return(p);
}
Not bad but still had one serious mistake.
int main(void)
{
char blah[] = "abcdefghijklm";
char *test;
char *test2;
char *test3;
char *test4;

test = left(blah, 10);
test2 = right(blah, 10);
test3 = chreplace(blah, 2, 'Q');
test4 = section(blah, 4, 10);
puts(test);
puts(test2);
puts(test3);
puts(test4);
Lots of allocating of memory in the functions but absolutely not call to
free(). That would be a memory leak.

free(test4);
free(test3);
free(test2);
free(test);
return 0;
}
Comments and improvements are welcome, flames to if appropriate.
--
------
Materialised

perl -e 'printf "%silto%c%sck%ccodegurus%corg%c", "ma", 58, "mi", 64,
46, 10;'


--
Send e-mail to: darrell at cs dot toronto dot edu
Don't send e-mail to vi************@whitehouse.gov
Nov 14 '05 #3

P: n/a
Materialised wrote:
Hi everyone,
I seen the post by Rob Morris, and thought that I would double check
that I was using pointers in the correct way. So I written the following
string functions to test. I know soem can be iumplimented using the
standard libary, but I just wanted to test writing my own functions.
They work ok, but I would like some feed back on any issues you can see
with them etc
Just a minor note on your use of int.
As far as I think your string functions
will never work with negative values.
So you may want to consider using size_t instead.
char *left(char *string, int count)

char *left(const char *string, size_t count)

etc.

Best regards,
Robert Bachmann
--
Ro*************@rbdev.net |) |)
http://rb.rbdev.net |\.|).
Nov 14 '05 #4

P: n/a
Materialised wrote:
Hi everyone,
I seen the post by Rob Morris, and thought that I would double check
that I was using pointers in the correct way. So I written the following
string functions to test. I know soem can be iumplimented using the
standard libary, but I just wanted to test writing my own functions.
They work ok, but I would like some feed back on any issues you can see
with them etc

Good.
First, document the functions. Tell us the specification.
Second, functions which allocate memory, return a pointer and expect
the caller to free the memory make me nervous. Your first example
below will illustrate nicely.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char *left(char *string, int count)
{
char *p;
int i;
p = malloc((count * sizeof(char)+1));
if(!p){
printf("Cannot allocate memory\n");
exit(1);
}
for(i = 0; i <= count -1; i++) {
p[i] = string[i];
}
p[i++] = '\0';

return(p);

} In dBASE, FoxPro, Clipper we have the very useful..

LEFT(<cString>, <nCount) -> cSubstring

...which we use like this..

phone = '7035551212' // a 10-character string
area = left(phone,3) // a 3-char string '703'
number = right(phone,4) // 4-char '1212'
exhg = left(right(phone,7),3) // '555'

These are higher level languages than C. The targets of the
assignments are created by the assignment itself. Replicating this
in C will keep you awake nights. :-)


char *right(char *string, int count)
{
char *p;
int len, i, j = 0;
p = malloc((count * sizeof(char)+1));
if(!p){
printf("Cannot allocate memory\n");
exit(1);
}
len = strlen(string);
for(i = (len - count); i <= len; i++){
p[j] = string[i];
j++;
}

p[j++] = '\0';
return(p);

}

char *chreplace(char *string, int count, char rep)
{
char *p;
p = malloc((sizeof(string)+1));
if(!p){
printf("Cannot allocate memory\n");
exit(1);
}
count--;
strcpy(p, string);
p[count] = rep;

return(p);
}

char *section(char *string, int from, int to)
{
char *p;
int i, j = 0;

p = malloc(((to - from) * sizeof(char)+1));
if(!p){
printf("Cannot allocate memory\n");
exit(1);
}
for( i = from; i <= to; i++) {
p[j] = string[i];
j++;
}
p[j++] = '\0';

return(p);
}
int main(void)
{
char blah[] = "abcdefghijklm";
char *test;
char *test2;
char *test3;
char *test4;

test = left(blah, 10);
test2 = right(blah, 10);
test3 = chreplace(blah, 2, 'Q');
test4 = section(blah, 4, 10);
puts(test);
puts(test2);
puts(test3);
puts(test4);
return 0;
}

Comments and improvements are welcome, flames to if appropriate.


The 'sizeof(char)' thing is wrong and ugly. Take your pick.

Be aware and beware..

int i, to = 10;

for (i = 0; i <= to; ++i) {
body();
}
... will execute body() eleven times.
--
Joe Wright mailto:jo********@comcast.net
"Everything should be made as simple as possible, but not simpler."
--- Albert Einstein ---
Nov 14 '05 #5

P: n/a
Materialised wrote:
Hi everyone,
I seen the post by Rob Morris, and thought that I would double check
that I was using pointers in the correct way. So I written the following
string functions to test. I know soem can be iumplimented using the
standard libary, but I just wanted to test writing my own functions.
They work ok, but I would like some feed back on any issues you can see
with them etc

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char *left(char *string, int count)
{
char *p;
int i;
p = malloc((count * sizeof(char)+1));
if(!p){
printf("Cannot allocate memory\n");
exit(1);
}
for(i = 0; i <= count -1; i++) {
p[i] = string[i];
}
p[i++] = '\0';

return(p);

}

char *right(char *string, int count)
{
char *p;
int len, i, j = 0;
p = malloc((count * sizeof(char)+1));
if(!p){
printf("Cannot allocate memory\n");
exit(1);
}
len = strlen(string);
for(i = (len - count); i <= len; i++){
p[j] = string[i];
j++;
}

p[j++] = '\0';
return(p);

}

char *chreplace(char *string, int count, char rep)
{
char *p;
p = malloc((sizeof(string)+1));
if(!p){
printf("Cannot allocate memory\n");
exit(1);
}
count--;
strcpy(p, string);
p[count] = rep;

return(p);
}

char *section(char *string, int from, int to)
{
char *p;
int i, j = 0;

p = malloc(((to - from) * sizeof(char)+1));
if(!p){
printf("Cannot allocate memory\n");
exit(1);
}
for( i = from; i <= to; i++) {
p[j] = string[i];
j++;
}
p[j++] = '\0';

return(p);
}
int main(void)
{
char blah[] = "abcdefghijklm";
char *test;
char *test2;
char *test3;
char *test4;

test = left(blah, 10);
test2 = right(blah, 10);
test3 = chreplace(blah, 2, 'Q');
test4 = section(blah, 4, 10);
puts(test);
puts(test2);
puts(test3);
puts(test4);
return 0;
}

Comments and improvements are welcome, flames to if appropriate.

Just a question,
I have taken all the people who replied comments to heart, and I am glad
for your feadback.
What I dont understand is what is wrong with sizeof(char)? True char may
be defined as 1 on most architectures. But does the way I have
referenced it require extra CPU useage or something?

Sorry if thats a dumb question..
--
------
Materialised

perl -e 'printf "%silto%c%sck%ccodegurus%corg%c", "ma", 58, "mi", 64,
46, 10;'
Nov 14 '05 #6

P: n/a
On Tue, 11 May 2004 01:56:17 +0100, Materialised <Ma**********@privacy.net>
wrote:
I have taken all the people who replied comments to heart, and I am glad
for your feadback.
What I dont understand is what is wrong with sizeof(char)? True char may
be defined as 1 on most architectures. But does the way I have
referenced it require extra CPU useage or something?

Sorry if thats a dumb question..


Not dumb at all. The Standard spells it out as follows (6.5.3.4/3):

"When applied to an operand that has type char, unsigned char, or signed
char, (or a qualified version thereof) the result is 1."

So sizeof(char) is 1, period. Which makes writing it out a bit redundant,
that's all.
-leor
--
Leor Zolman --- BD Software --- www.bdsoft.com
On-Site Training in C/C++, Java, Perl and Unix
C++ users: download BD Software's free STL Error Message Decryptor at:
www.bdsoft.com/tools/stlfilt.html
Nov 14 '05 #7

P: n/a
Leor Zolman wrote:
char, (or a qualified version thereof) the result is 1."

So sizeof(char) is 1, period. Which makes writing it out a bit redundant,
that's all.
-leor

So if my personal preference is to use sozeof(char) there will be no
portability issues with this?
Because tbh, (for me) it seems easier to remember.

--
------
Materialised

perl -e 'printf "%silto%c%sck%ccodegurus%corg%c", "ma", 58, "mi", 64,
46, 10;'
Nov 14 '05 #8

P: n/a
Leor Zolman wrote:
On Mon, 10 May 2004 15:11:42 +0100, Materialised <Ma**********@privacy.net>
wrote:

Hi everyone,
I seen the post by Rob Morris, and thought that I would double check
that I was using pointers in the correct way. So I written the following
string functions to test. I know soem can be iumplimented using the
standard libary, but I just wanted to test writing my own functions.
They work ok, but I would like some feed back on any issues you can see
with them etc

Okay, I'll point out some things I see. I'm sure there's much else others
will catch.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char *left(char *string, int count)

Since you're not modifying string, define it as pointer-to-const:

char *left(const char *string, int count)
(or, Dan Saks style)
char *left(char const *string, int count)
{
char *p;
int i;
p = malloc((count * sizeof(char)+1));

I don't know if there's a group consensus or not on whether it is worth the
trouble to say 'sizeof(char)' when the value is always 1. Personally, I'd
leave it out for the sake of simplicity:
p = malloc(count + 1);

Except for one thing: you don't know if you'll need all of that space.
What if someone specifies count as 10000? Wouldn't you be better of
figuring out, first, how much space you're /really/ going to need and just
allocating that?

if(!p){
printf("Cannot allocate memory\n");
exit(1);
}
for(i = 0; i <= count -1; i++) {
p[i] = string[i];

Another problem if count is too big is you'll keep going right off the end
of the source array here (undefined behavior).

}
p[i++] = '\0';

return(p);

}

char *right(char *string, int count)

All the same issues as above (well, now if count is too big you'll be
trying to read out of memory /before/ string instead of after it...)

{
char *p;
int len, i, j = 0;
p = malloc((count * sizeof(char)+1));
if(!p){
printf("Cannot allocate memory\n");
exit(1);
}
len = strlen(string);
for(i = (len - count); i <= len; i++){
p[j] = string[i];
j++;
}

p[j++] = '\0';
return(p);

}

char *chreplace(char *string, int count, char rep)


blah blah const blah blah...
{
char *p;
p = malloc((sizeof(string)+1));
if(!p){
printf("Cannot allocate memory\n");
exit(1);
}
count--;
strcpy(p, string);
p[count] = rep;


No sanity checking on count (again).

return(p);


don't need parens there. return is not a function.

}

char *section(char *string, int from, int to)


const,
sanity checking of from/to

{
char *p;
int i, j = 0;

p = malloc(((to - from) * sizeof(char)+1));
if(!p){
printf("Cannot allocate memory\n");
exit(1);
}
for( i = from; i <= to; i++) {
p[j] = string[i];
j++;
}
p[j++] = '\0';

return(p);
}
int main(void)
{
char blah[] = "abcdefghijklm";
char *test;
char *test2;
char *test3;
char *test4;

test = left(blah, 10);
test2 = right(blah, 10);
test3 = chreplace(blah, 2, 'Q');
test4 = section(blah, 4, 10);
puts(test);
puts(test2);
puts(test3);
puts(test4);
return 0;
}

Comments and improvements are welcome, flames to if appropriate.

That should give you a bit to work on...
-leor

Thats for your comments,
as regard to the sainity checking, thanks, the advice was well taken :)
I did think if including it actually, but as it was only a personal
example, I thought it wouldnt be a issue, but i understand if I wish to
be a good programmer, i should get into the habbit now.

--
------
Materialised

perl -e 'printf "%silto%c%sck%ccodegurus%corg%c", "ma", 58, "mi", 64,
46, 10;'
Nov 14 '05 #9

P: n/a
Darrell Grainger wrote:
<snip>


Lots of allocating of memory in the functions but absolutely not call to
free(). That would be a memory leak.

free(test4);
free(test3);
free(test2);
free(test);
return 0;
}

Am I wrong in assuming that memory is automatically free()'ed at the end
of the program?
--
------
Materialised

perl -e 'printf "%silto%c%sck%ccodegurus%corg%c", "ma", 58, "mi", 64,
46, 10;'
Nov 14 '05 #10

P: n/a
On Tue, 11 May 2004 03:51:29 +0100, Materialised <Ma**********@privacy.net>
wrote:
Leor Zolman wrote:
char, (or a qualified version thereof) the result is 1."

So sizeof(char) is 1, period. Which makes writing it out a bit redundant,
that's all.
-leor

So if my personal preference is to use sozeof(char) there will be no
portability issues with this?
Because tbh, (for me) it seems easier to remember.


That's okay, it will work just fine in either style. As far as I'm
concerned, it is really six of one and a half dozen of the other; putting
it in is "unnecessary", leaving it out is inconsistent with other idiomatic
uses of sizeof. What can you do.
-leor
--
Leor Zolman --- BD Software --- www.bdsoft.com
On-Site Training in C/C++, Java, Perl and Unix
C++ users: download BD Software's free STL Error Message Decryptor at:
www.bdsoft.com/tools/stlfilt.html
Nov 14 '05 #11

P: n/a
Robert Bachmann wrote:
Materialised wrote:
Hi everyone,
I seen the post by Rob Morris, and thought that I would double check
that I was using pointers in the correct way. So I written the
following string functions to test. I know soem can be iumplimented
using the standard libary, but I just wanted to test writing my own
functions. They work ok, but I would like some feed back on any issues
you can see with them etc

Just a minor note on your use of int.
As far as I think your string functions
will never work with negative values.
So you may want to consider using size_t instead.

<snip>
Please ignore my ignorance, but if I had the string:

chat blah[] = "abcdef";

Why would I need to reference a negative value of the string?

--
------
Materialised

perl -e 'printf "%silto%c%sck%ccodegurus%corg%c", "ma", 58, "mi", 64,
46, 10;'
Nov 14 '05 #12

P: n/a
Materialised <Ma**********@privacy.net> wrote:
Darrell Grainger wrote:
Lots of allocating of memory in the functions but absolutely not call to
free(). That would be a memory leak.

free(test4);
free(test3);
free(test2);
free(test);

return 0;
}

Am I wrong in assuming that memory is automatically free()'ed at the end
of the program?


You're wrong in assuming that it is guaranteed. Of course, the same
thing could be said about memory that _is_ explicitly free()d, but
you're just ever so slightly more wrong about programs that do not clean
up after their own butts like their mama (i.e., you!) taught them to.

Besides, you may be wrong in assuming that this part of the code is
always going to stand alone. If it is ever incorporated in a larger
program, which, granted, is unlikely for a test program but rather more
plausible for real code, you'll be glad that you don't have to stop it
from leaking code then, when you have so many other compatibility issues
to think of.

Richard
Nov 14 '05 #13

P: n/a
On Tue, 11 May 2004 03:59:16 +0100, Materialised wrote:

Am I wrong in assuming that memory is automatically free()'ed at the end
of the program?


Yes. That assumption is not portable and can cause problems on some
systems.

--
yvoregnevna gjragl-guerr gjb-gubhfnaq guerr ng lnubb qbg pbz
To email me, rot13 and convert spelled-out numbers to numeric form.
"Makes hackers smile" makes hackers smile.

Nov 14 '05 #14

P: n/a
Materialised <Ma**********@privacy.net> writes:
Darrell Grainger wrote:
<snip>
Lots of allocating of memory in the functions but absolutely not call
to free(). That would be a memory leak.
I usually use the term "memory leak" to refer to memory which can no
longer be accessed while the program runs. That's not the case here;
there are valid pointers to the allocated memory blocks until `main'
returns.
free(test4);
free(test3);
free(test2);
free(test);
return 0;
}

Am I wrong in assuming that memory is automatically free()'ed at the end
of the program?


Neither behavior is guaranteed, but manually freeing memory at the end
of the program has advantages as well as disadvantages. If you search
the archives, you'll see that there is no consensus in this group about
this question.

Martin
--
,--. Martin Dickopp, Dresden, Germany ,= ,-_-. =.
/ ,- ) http://www.zero-based.org/ ((_/)o o(\_))
\ `-' `-'(. .)`-'
`-. Debian, a variant of the GNU operating system. \_/
Nov 14 '05 #15

P: n/a
Materialised <Ma**********@privacy.net> wrote in message news:<2g***********@uni-berlin.de>...
Darrell Grainger wrote:

Lots of allocating of memory in the functions but absolutely not call to
free(). That would be a memory leak.

free(test4);
free(test3);
free(test2);
free(test);
return 0;
}


Am I wrong in assuming that memory is automatically free()'ed at the end
of the program?


you are correct, but it is good practice for software to clean up behind
itself. Not all programs have "ends", they are supposed to run pretty well
continuously. Consider the joy that would greet this error message:-

"airbus.c line 5211: Assertion failed: malloced_val != NULL"

--
Nick Keighley

-pedantic
This option is not intended to be useful; it exists only to satisfy
pedants who would otherwise claim that GNU CC fails to support the
ANSI standard.
(Using and Porting GNU CC)
Nov 14 '05 #16

P: n/a
Martin Dickopp <ex****************@zero-based.org> wrote:
Materialised <Ma**********@privacy.net> writes:
Darrell Grainger wrote:
free(test4);
free(test3);
free(test2);
free(test);
return 0;
}

Am I wrong in assuming that memory is automatically free()'ed at the end
of the program?


Neither behavior is guaranteed, but manually freeing memory at the end
of the program has advantages as well as disadvantages.


Hmmm... I can't really see any disadvantages here - except the extra
typing, which is insignificant.

Richard
Nov 14 '05 #17

P: n/a
Materialised <Ma**********@privacy.net> wrote in message news:<2g***********@uni-berlin.de>...
Robert Bachmann wrote:
Just a minor note on your use of int.
As far as I think your string functions
will never work with negative values.
So you may want to consider using size_t instead.

Please ignore my ignorance, but if I had the string:

chat blah[] = "abcdef";

Why would I need to reference a negative value of the string?


quite. That's why he's suggesting you don't allow such calls. Another way
would be to check for values less than zero inside the function. Perhaps
using assert().
--
Nick Keighley

We recommend, rather, that users take advantage of the extensions of
GNU C and disregard the limitations of other compilers. Aside from
certain supercomputers and obsolete small machines, there is less
and less reason ever to use any other C compiler other than for
bootstrapping GNU CC.
(Using and Porting GNU CC)
Nov 14 '05 #18

P: n/a
"Richard Bos" <rl*@hoekstra-uitgeverij.nl> wrote in message
news:40****************@news.individual.net...
Martin Dickopp <ex****************@zero-based.org> wrote:
Materialised <Ma**********@privacy.net> writes:
Am I wrong in assuming that memory is automatically free()'ed at the
end of the program?


Neither behavior is guaranteed, but manually freeing memory at the end
of the program has advantages as well as disadvantages.


Hmmm... I can't really see any disadvantages here - except the extra
typing, which is insignificant.


The only one I know of (and it's OT) is that calls to free() are often
relatively expensive.
Nov 14 '05 #19

P: n/a
"Alex" <me@privacy.net> wrote:
"Richard Bos" <rl*@hoekstra-uitgeverij.nl> wrote in message
news:40****************@news.individual.net...
Martin Dickopp <ex****************@zero-based.org> wrote:
Neither behavior is guaranteed, but manually freeing memory at the end
of the program has advantages as well as disadvantages.


Hmmm... I can't really see any disadvantages here - except the extra
typing, which is insignificant.


The only one I know of (and it's OT) is that calls to free() are often
relatively expensive.


Possibly, and possibly not; in any case, at the end of the program it is
hardly likely to matter a lot, is it?

Richard
Nov 14 '05 #20

P: n/a
"Alex" <me@privacy.net> writes:
"Richard Bos" <rl*@hoekstra-uitgeverij.nl> wrote in message
news:40****************@news.individual.net...
Martin Dickopp <ex****************@zero-based.org> wrote:
> Materialised <Ma**********@privacy.net> writes:
>
> > Am I wrong in assuming that memory is automatically free()'ed at the
> > end of the program?
>
> Neither behavior is guaranteed, but manually freeing memory at the end
> of the program has advantages as well as disadvantages.


Hmmm... I can't really see any disadvantages here - except the extra
typing, which is insignificant.


The only one I know of (and it's OT) is that calls to free() are often
relatively expensive.


Yes, that's what I was thinking about.

Martin
--
,--. Martin Dickopp, Dresden, Germany ,= ,-_-. =.
/ ,- ) http://www.zero-based.org/ ((_/)o o(\_))
\ `-' `-'(. .)`-'
`-. Debian, a variant of the GNU operating system. \_/
Nov 14 '05 #21

P: n/a
rl*@hoekstra-uitgeverij.nl (Richard Bos) writes:
"Alex" <me@privacy.net> wrote:
"Richard Bos" <rl*@hoekstra-uitgeverij.nl> wrote in message
news:40****************@news.individual.net...
> Martin Dickopp <ex****************@zero-based.org> wrote:
>
> > Neither behavior is guaranteed, but manually freeing memory at the end
> > of the program has advantages as well as disadvantages.
>
> Hmmm... I can't really see any disadvantages here - except the extra
> typing, which is insignificant.


The only one I know of (and it's OT) is that calls to free() are often
relatively expensive.


Possibly, and possibly not; in any case, at the end of the program it is
hardly likely to matter a lot, is it?


That depends on the situation. In situations where processes terminate
very often[*], it may take a significant amount of CPU.

Martin

[*] A common example is a server program which creates a new process for
every incoming request.

--
,--. Martin Dickopp, Dresden, Germany ,= ,-_-. =.
/ ,- ) http://www.zero-based.org/ ((_/)o o(\_))
\ `-' `-'(. .)`-'
`-. Debian, a variant of the GNU operating system. \_/
Nov 14 '05 #22

P: n/a
In <40****************@news.individual.net> rl*@hoekstra-uitgeverij.nl (Richard Bos) writes:
"Alex" <me@privacy.net> wrote:
"Richard Bos" <rl*@hoekstra-uitgeverij.nl> wrote in message
news:40****************@news.individual.net...
> Martin Dickopp <ex****************@zero-based.org> wrote:
>
> > Neither behavior is guaranteed, but manually freeing memory at the end
> > of the program has advantages as well as disadvantages.
>
> Hmmm... I can't really see any disadvantages here - except the extra
> typing, which is insignificant.


The only one I know of (and it's OT) is that calls to free() are often
relatively expensive.


Possibly, and possibly not; in any case, at the end of the program it is
hardly likely to matter a lot, is it?


To some people, "stealing" CPU cycles from programs that are still
running for no *good* reason DOES matter.

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Da*****@ifh.de
Nov 14 '05 #23

P: n/a
Richard Bos <rl*@hoekstra-uitgeverij.nl> wrote:
"Alex" <me@privacy.net> wrote:
"Richard Bos" <rl*@hoekstra-uitgeverij.nl> wrote in message
news:40****************@news.individual.net...
> Martin Dickopp <ex****************@zero-based.org> wrote:
>
> > Neither behavior is guaranteed, but manually freeing memory at the end
> > of the program has advantages as well as disadvantages.
>
> Hmmm... I can't really see any disadvantages here - except the extra
> typing, which is insignificant.


The only one I know of (and it's OT) is that calls to free() are often
relatively expensive.

Possibly, and possibly not; in any case, at the end of the program it is
hardly likely to matter a lot, is it?


If a program unnecessarily takes N seconds to terminate, it is likely
to matter for large enough value of N.

--
Alex Monjushko (mo*******@hotmail.com)
Nov 14 '05 #24

P: n/a

In article <40****************@news.individual.net>, rl*@hoekstra-uitgeverij.nl (Richard Bos) writes:
"Alex" <me@privacy.net> wrote:
"Richard Bos" <rl*@hoekstra-uitgeverij.nl> wrote in message
news:40****************@news.individual.net...
Martin Dickopp <ex****************@zero-based.org> wrote:

> Neither behavior is guaranteed, but manually freeing memory at the end
> of the program has advantages as well as disadvantages.

Hmmm... I can't really see any disadvantages here - except the extra
typing, which is insignificant.


The only one I know of (and it's OT) is that calls to free() are often
relatively expensive.


Possibly, and possibly not; in any case, at the end of the program it is
hardly likely to matter a lot, is it?


There are plenty of situations where program-exit latency can be an
issue. It may simply be a usability or quality-of-experience one,
where it's just a matter of making a user wait longer than necessary;
but it may also affect overall system performance, if other tasks
need to wait for the exiting program.

Another possible disadvantage is that explicitly freeing all allocated
areas at the end of the program increases maintenance effort (because
a maintainer who alters the program's memory allocation must now take
that into account), and introduces a source of maintenance bugs (a
maintainer adds a free for an area elsewhere in the logic, not realizing
that the program will attempt to free it again at exit).

In general, the arguments for "automatic free on exit" (for implementa-
tions that do so) are similar to those in favor of garbage collection.

That's not to say that any of those arguments are necessarily compelling,
just that there are potentially disadvantages, under some rubrics, for
explicitly freeing everything before exiting.

--
Michael Wojcik mi************@microfocus.com

Pocket #16: A Ventriloquist's "Helper" -- Recordings for Divers Occasions,
especially cries to put in the mouths of enemies -- "God Bless Captain
Vere!" "Les jeux sont faits!" &c. -- Joe Green
Nov 14 '05 #25

P: n/a
Materialised wrote:
Hi everyone,
I seen the post by Rob Morris, and thought that I would double check
that I was using pointers in the correct way. So I written the following
string functions to test. I know soem can be iumplimented using the
standard libary, but I just wanted to test writing my own functions.
They work ok, but I would like some feed back on any issues you can see
with them etc

I would like to thank everyone for their comments and suggestions. I
have now modified the code to include sanity checking, this is the
modified version,

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char *left(char *string, int count)
{
char *p;
int i;
if(strlen(string) <= 0 ) {
p = NULL;
return p;
}
if(count > strlen(string)) {
p = NULL;
return p;
}
if(!count) {
p = NULL;
return p;
}
p = malloc((count * sizeof(char)+1));
if(!p){
p = NULL;
return p;
}
for(i = 0; i <= count -1; i++) {
p[i] = string[i];
}
p[i++] = '\0';

return p;

}

char *right(char *string, int count)
{
char *p;
int len, i, j = 0;
if(strlen(string) <= 0 ) {
p = NULL;
return p;
}
if(count > strlen(string)) {
p = NULL;
return p;
}
if(!count) {
p = NULL;
return p;
}
p = malloc((count * sizeof(char)+1));
if(!p){
p = NULL;
return p;
}
len = strlen(string);
for(i = (len - count); i <= len; i++){
p[j] = string[i];
j++;
}

p[j++] = '\0';
return p;

}

char *chreplace(char *string, int count, char rep)
{
char *p;
if(strlen(string) <= 0 ) {
p = NULL;
return p;
}
if(count > strlen(string)) {
p = NULL;
return p;
}
if(!count){
p = NULL;
return p;
}
if(!rep) {
p = NULL;
return p;
}
p = malloc((count * sizeof(char)+1));
if(!p){
p = NULL;
return p;
}
count--;
strcpy(p, string);
p[count] = rep;

return p;
}

char *section(char *string, int from, int to)
{
char *p;
int i, j = 0;
if(strlen(string) <= 0) {
p = NULL;
return p;
}
if(!from) {
p = NULL;
return p;
}
if(!to) {
p = NULL;
return p;
}
if(from > strlen(string)) {
p = NULL;
return p;
}
if(to > strlen(string)){
p = NULL;
return p;
}
p = malloc(((to - from) * sizeof(char)+1));
if(!p){
p = NULL;
return p;
}
for( i = from; i <= to; i++) {
p[j] = string[i];
j++;
}
p[j++] = '\0';

return p;
}

int main(void)
{
char blah[] = "abcdefghijklm";
char *test;
char *test2;
char *test3;
char *test4;

test = left(blah, 10);
test2 = right(blah, 10);
test3 = chreplace(blah, 2, 'Q');
test4 = section(blah, 4, 10);
if(test)
puts(test);
if(test2)
puts(test2);
if(test3)
puts(test3);
if(test4)
puts(test4);
free(test);
free(test2);
free(test3);
free(test4);
return 0;
}

Any comments or advice on this version are more than welcome.
--
------
Materialised

perl -e 'printf "%silto%c%sck%ccodegurus%corg%c", "ma", 58, "mi", 64,
46, 10;'
Nov 14 '05 #26

P: n/a
Materialised <Ma**********@privacy.net> wrote:

I would like to thank everyone for their comments and suggestions. I
have now modified the code to include sanity checking, this is the
modified version,
Your code works but there is a lot of redundant code.
I have commented below on your left() function only (similar comments
will apply to the rest of your code).
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char *left(char *string, int count)
{
char *p;
int i;
if(strlen(string) <= 0 ) {
p = NULL;
return p;
return NULL;

Out of interest, what motivated you to write "p = NULL; return p;" ?
}
if(count > strlen(string)) {
p = NULL;
return p;
}
if(!count) {
p = NULL;
return p;
}
You do not check if count is less than 0 (which would produce
undefined behaviour), and you do not check if string is NULL.
Both of these checks would usually be included in "sanity checks".

On the other hand, you do return NULL if count is exactly zero.
It might be more sensible to return a blank string in this case
(but then again it might not -- your call).

You do strlen(string) twice in this function, which is a waste.
In fact you do not need to test if it is less than or equal to zero,
because it cannot be negative, and your function will work correctly
if it is zero (because then one of the checks on "count" will fail).

You could do the checks like this:

if (count <= 0) /* or (count < 0) if you want to allow 0 */
return NULL;

if (string == NULL) /* (optional) */
return NULL;

if (count > strlen(string))
return NULL;
p = malloc((count * sizeof(char)+1));
p = malloc((count+1) * sizeof(char));

You've discussed why you like to have "sizeof(char)" instead of "1":
so that the form of the malloc() call is the same for whichever type
you are using. However your code would have been wrong if it were
changed to another type, eg:

wchar_t *w;
w = malloc(count * sizeof(wchar_t) + 1);

because you want (count + 1) wchars, not (count) wchars and 1 byte.
if(!p){
p = NULL;
return p;
}
p is already NULL so why set it to NULL again ??
for(i = 0; i <= count -1; i++) {
for (i = 0; i < count; i++)

Although it means the same thing, this is more idiomatic (ie. more
readable) to the majority of C programmers.
p[i] = string[i];
}
p[i++] = '\0';
i is never used after this statement, so incrementing it is a waste
of time.

Also possible (more efficient, and not requiring another variable) was:

memcpy(p, string, count);
p[count] = '\0';

return p;

}


Here is how I might have written that function (note, this is not to
say that you should do it my way -- just to give you some more ideas)

char *left( char *string, int count )
{
char *p;

if ( !string || count < 0 || count > strlen(string) )
return NULL;

p = malloc(count+1);
if (p)
{
memcpy(p, string, count);
p[count] = '\0';
}
return p;
}
Nov 14 '05 #27

This discussion thread is closed

Replies have been disabled for this discussion.