More C newbieness

Hai,

I've tried to write a function that takes a string and allocates a sufficent amount of memory and the copies the string there.

But i have run into a minor dilemma.

My code looks like this:
Code:
char *stringcopy(char *str){
     
     int len = strlen(str);
     
     char *p = (char *)malloc(len *sizeof(char));
     char *ptr = &p[0];
     
     while((*p++ = *str++) != '\0');
     
     return ptr;
     
     }

When the call to the function have finished you're supposed to clean up after yourself by calling free(), but p is local to the function and can't be reached from outside. And calling free() just after return defeats the purpose by revoking the allocated memory.

But then, maybe this is the wrong way to do this kind of thing?

Minor side question: How does the compiler know that *sizeof(char) does not refer to a pointer, but a multiplication?
 
You want to allocate len + 1 bytes, not just len -- strlen returns the size of the string sans the null terminator (i.e. strlen("") == 0), but you need to have space for the null terminator there, hence the + 1.

And if you have a function like that, then your caller will have to know the returned memory is malloc'd and that they have to free it later. So a call might look like:
Code:
char* copy = stringcopy("Foo");
have_fun(copy);
free(copy);

A better way would probably be the way strcpy is done: let the caller pass you a pointer to a buffer where they want the string to be stored, and it's up to them when and where they allocate the buffer and when and where they free it.

And I'm not sure how exactly GCC's parser is implemented, but the compiler can see that the * is the binary operator, because there is "len" before it. If you wrote malloc(*sizeof(char));, it would indeed think you're trying to dereference a pointer and yell at you for trying to apply the unary-* operator to a size_t type.
 
One more small detail, in C you don't have to cast void* to T*

Code:
char *p = malloc(len * sizeof(char));

even better

Code:
char *p = malloc(len * sizeof(*p));
 
Back
Top