This question already has an answer here:
So, i am trying to implement my own strcpy to have a better understanding of how pointers work in C, and so far i am at a loss. I tried a lot of different approaches, tried using code from the net to maybe base mine on later, but even those wont work.
I believe i might be calling the function in the wrong way on the main method. I am passing a pointer of the variable to the function, so that the function can change the value of the variable and on the function call, i am giving the adress of the pointer so the method can get the correct data. At least i believe this is how it works, from what i could understand at any rate.
Here are the functions and the method calls:
Function call:
void my_strcpy( char *dest, const char* src ) {
dest = malloc(sizeof(src));
while ( src != '\0' ) {
*dest = *src;
src++;
dest++;
}
}
Main:
int main () {
const char* s = "Hello World";
char* test = 'd';
my_strcpy( &test, &s ); // Suposed to change test form d to Hello World.
printf("Changed String: " );
printf( "%c", test );
return 0;
}
PS: I tried using test as a string bigger than s to see if it was a memory allocation problem but it does not appear to be so. Any help is greatly apreciated as i have been stuck in this for hours...
PS: I've looked into the question and examples of how to change the variable and can do it using a simple int. But i cannot do it when using char*. Hence the post. I apologize if the issue is the same but i just cannot understand what i'm doing wrong here. Please, have patience with me as i am a beginner in C.
The key point is that arguments are passed by value in C.
Hence any change of a formal argument is never seen by the caller function.
At last, your my_strcpy
is not behaving like the standard strcpy
(which does not allocate memory using malloc
). And your use of malloc
is wrong, since sizeof(src)
is always sizeof(char*)
(i.e. 8 on Linux/x86-64).
Here is a better version:
void my_strcpy( char *dest, const char* src ) {
while ( *src != '\0' ) {
*dest = *src;
src++;
dest++;
}
*dest = '\0'; // zero terminate the string
}
Notice that strcpy
(and my_strcpy
) is intrinsically dangerous because you may have buffer overflow (so use strncpy
more often). A typical use case would be
char buf[80];
my_strcpy(buf, "hello I am here");
so we have local memory (on the call stack typically) and we copy into it. If the literal string was very long (e.g. more than 80 characters) we would have a buffer overflow.
BTW, your test while(src != '\0')
was very wrong. A pointer is not the same the pointed value. Your wrong test would typically loop a billion times on a 32 bits machine and would crash before reaching the terminating condition src == NULL
Also in practice strcpy
is often known by optimizing compilers like GCC which may even generate a loop, not a function call to a standard function, when compiling it.
Several of your mistakes would probably have been spotted by your compiler (e.g. GCC) if you enable all warnings in your compiler (which you always should), so compile e.g. with gcc -Wall -Wextra -g
(to get all warnings, some more, and debug information) then use the debugger gdb
to run your program step by step.
In practice, when possible, have functions returning pointers, like
char* my_almost_strdup(const char*src) {
size_t ln = strlen(src);
char* newptr = malloc(ln+1);
if (!newptr) { perror("my_strdup"); exit(EXIT_FAILURE); };
strcpy (newptr, src);
return newptr;
}
this is a bit like the standard strdup
except that I am catching the out-of-memory error case (when malloc
fails). It is common to just show some error message and exit in that failing case, but you should always handle malloc
failure
Read more about C dynamic memory management and document your memory conventions (when having a function allocating memory in heap thru malloc
or calloc
etc... you need to document who is in charge of freeing it and how).
Be afraid of undefined behavior and of memory leaks. Use valgrind if available.
Read a bit more about garbage collection (it is a very useful terminology and concept). You might want to code some C programs using Boehm conservative garbage collector (but using Boehm's GC is a whole program decision).
In your main
my_strcpy( &test, &s ); // VERY BAD
is many times wrong (undefined behavior because of buffer overflow). You should pass an address of a memory zone able to contain the string (including its terminating zero byte), and the second argument does not have the right type (&s
is a char**
not a const char*
).
You don't need the & to reference the char *
because it is already a pointer to a character, you don't want char **
which is a pointer to a pointer to a character.
I patched it up:
void my_strcpy(char** dest, const char* src) {
const char * srcTemp = src;
int i = 1; //+1 for null char
while (*srcTemp != '\0') {
srcTemp++;
i++;
}
char * destTemp = (char*)malloc(sizeof(char)*i);
*dest = destTemp;
while (*src != '\0') {
*destTemp = *src;
src++;
*destTemp++;
}
*destTemp = *src; //copy null char
}
int _tmain(int argc, _TCHAR* argv[])
{
const char* s = "Hello World";
char* test = 0;
my_strcpy(&test, s); // Suposed to change test form d to Hello World.
printf("Changed String: ");
printf("%s", test);
return 0;
}
来源:https://stackoverflow.com/questions/29443151/c-implementention-of-strcpy-does-not-change-variable-value