Chaning/allocating char* function parameters

J

Johnathan Doe

Why is is necessary to write a function that allocates memory for, or
changes, a pointer to a char array using char** instead of char*?

E.g.

void modify_string( char** string )
{
if( string == NULL )
return;

if( *string != NULL )
free( *string );

*string = ( char * )calloc( n, sizeof( char ) );
strncpy( *string, "Whatever", n );
}

If this is written using the parameter char** string as char *string it
doesn't work (? or only if that function passes the string to some other
function which allocates and initialises the string?) Same with passing
in a pointer to a structure that needs to be allocated and filled in
with pointers to strings that also need allocating.

E.g.
void f( struct foo **f )
{
*f = malloc( sizeof( struct foo ) );
(*f)->string = ( char *)calloc( n, sizeof( char ) );
...
}

Does this have something to do with C parameters being passed by value?
E.g. you get a copy of a pointer and not the actual pointer, hence you
need a copy of a pointer to the actual pointer or somesuch?

Thanks,
Johnathan
 
J

Jack Klein

Why is is necessary to write a function that allocates memory for, or
changes, a pointer to a char array using char** instead of char*?

E.g.

void modify_string( char** string )
{
if( string == NULL )
return;

if( *string != NULL )
free( *string );

*string = ( char * )calloc( n, sizeof( char ) );

Casting the value returned by malloc() or calloc() is not recommended
by most experienced C programmers, at least most of those who post
here. It can prevent an appropriate error message if you have
forgotten to include <string.h> and do not have a proper prototype in
scope for the function, which results in undefined behavior.

It is also never necessary to use the expression "sizeof(char)", since
this is 1 by definition and always will be. With types other than
char, using sizeof(type) can introduce a maintenance issue if you
change the type that the pointer points to, but forget to change the
type in the sizeof expression.

The most robust way to allocate memory to a pointer with calloc() uses
the sizeof the object. Consider:

int *ptr;

ptr = calloc(how_many, sizeof *ptr);

If later on you decide you need a greater range of numbers and you
change to:

long *ptr;

....the calloc() or malloc() call will still allocate the proper amount
of memory.

strncpy( *string, "Whatever", n );
}

If this is written using the parameter char** string as char *string it
doesn't work (? or only if that function passes the string to some other
function which allocates and initialises the string?) Same with passing
in a pointer to a structure that needs to be allocated and filled in
with pointers to strings that also need allocating.

E.g.
void f( struct foo **f )
{
*f = malloc( sizeof( struct foo ) );
(*f)->string = ( char *)calloc( n, sizeof( char ) );
...
}

Does this have something to do with C parameters being passed by value?
E.g. you get a copy of a pointer and not the actual pointer, hence you
need a copy of a pointer to the actual pointer or somesuch?

Thanks,
Johnathan

This is covered in http://www.eskimo.com/~scs/C-faq/q4.8.html in the
FAQ for this group.

Likewise it would be a good idea for you to look at all of section 7,
http://www.eskimo.com/~scs/C-faq/s7.html, devoted to memory allocation
issues.

And there's a lot of useful information in the rest of the FAQ as
well.
 
A

Al Bowers

Johnathan said:
Why is is necessary to write a function that allocates memory for, or
changes, a pointer to a char array using char** instead of char*?

E.g.

Look at faq question: http://www.eskimo.com/~scs/C-faq/q4.8.html
void modify_string( char** string )
Dynamic allocations can fail, so the function should give come
indicator of success or failure. You can make it a useful
function if you include a parameter that points to the new
string.

Ex:
int modify_string(char **oldstring, const char *newstring)
{
if( string == NULL )
return;

if( *string != NULL )

This test is really not neccessary. free(NULL) is defined by the
Standard. It simply does nothing.
free( *string );

*string = ( char * )calloc( n, sizeof( char ) );

Why not use function realloc. Then you would not need to use free
in this function.
strncpy( *string, "Whatever", n );
}

Here is a more useful definition of the function. It uses
function realloc for the allocation.

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

int modify_string( char** oldstring, const char *newstring )
{
char *tmp;

if( oldstring == NULL || newstring == NULL)
return 0;
if((tmp = realloc(*oldstring,strlen(newstring)+1)) == NULL)
return 0;
strcpy(tmp,newstring);
*oldstring = tmp;
return 1;
}

void free_string(char **str)
{
free(*str);
*str = NULL;
return;
}

int main(void)
{
char *buf = NULL; /* Iniatate NULL neccessary */

if(modify_string(&buf,"Bill Adams"))
{
printf("buf = \"%s\"\n",buf);
puts("modify buf.....");
if(modify_string(&buf,"George Washington"))
printf("buf = \"%s\"\n",buf);
else puts("Failed to modify");
}
else puts("Failed initial allocation");
free_string(&buf);
return 0;
}
 
J

Johnathan Doe

Hello Al,

Thankyou very much. This has been extremely useful.
I finally understand why sometimes my functions work
and sometimes they don't. :)

Took me a while to say thanks: internet connection
down. Thanks so much for the thought you put into
this response.

Kind Regards. :)
 
J

Johnathan Doe

Jack said:
int *ptr;

ptr = calloc(how_many, sizeof *ptr);

If later on you decide you need a greater range of numbers and you
change to:

long *ptr;

...the calloc() or malloc() call will still allocate the proper amount
of memory.

Thanks!!!

This is covered in http://www.eskimo.com/~scs/C-faq/q4.8.html in the
FAQ for this group.

Likewise it would be a good idea for you to look at all of section 7,
http://www.eskimo.com/~scs/C-faq/s7.html, devoted to memory allocation
issues.

And there's a lot of useful information in the rest of the FAQ as
well.

Doing now. Thanks heaps.

All this stuff fails to be mentioned in university textbooks. I
wonder why? It's conceptually fairly simple, so first year
texts leave a false impression that you have the skills to write
robust C software (or any software at all...) in C. Hmph!
 
A

August Derleth

Thanks!!!

Your textbook /really/ should have taught you this stuff already. I mean,
honestly...
Doing now. Thanks heaps.

Some people would suggest you at least browse the FAQ /before/ your first
post to the newsgroup. I didn't, however, so I'm in no position to judge. ;)
All this stuff fails to be mentioned in university textbooks. I
wonder why? It's conceptually fairly simple, so first year
texts leave a false impression that you have the skills to write
robust C software (or any software at all...) in C. Hmph!

Yes, this seems to be a problem endemic to textbooks about programming
languages. A few hints:

-If the title of the book says "for dummies", it is. Don't buy it.

-If the book gives all examples relative to a specific compiler or IDE, it
will spend more time discussing the compiler/IDE and its extensions than
the language. This may be what you want, but not when you're just
beginning with a language.

-Read reviews first. The Association of C and C++ Users has good reviews
online: http://www.accu.org/bookreviews/public/index.htm

For something C-specific, try "The C Programming Language, Second Edition"
by Brian W. Kernighan and Dennis M. Ritchie. They take you through the
/complete/ C language, as it stood in 1989 when it was first standardized.
The code they use is conformant to the standard most modern compilers
implement, which is helpful (the later standardization of 1999 hasn't
caught on yet, and it might never quite make it into the mainstream).
 

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
474,431
Messages
2,571,678
Members
48,796
Latest member
Greg L.

Latest Threads

Top