Confusion between passing and modifying char pointers in C (reference vs. value)
I was wondering if you could help me out with a C string problem I don't quite understand. I have a function to which I send 3 char开发者_Python百科 pointers. Within this function, the char pointers are shifted and modified correctly. However, when I return to the main function from which they are called, said functions are not changed. Am I passing by value be mistake? Here is an example of my code:
int main(void)
{
LPSTR path = (char*)malloc(strlen(START_PATH));
strcpy( path, START_PATH );
char* newstr = (char*)malloc(PATH_SIZE);
TrimVal(path, "*.*", newstr);
//Do Stuff
return 0;
}
void TrimVal(char* modify, char* string, char* newstr)
{
newstr[0] = '\0';
modify = strncat(newstr, modify, (strlen(modify) - strlen(string)));
return;
}
NOTE: Assume PATH_SIZE
is a size value, and START_PATH
is a char array
In doing this
modify = strncat(newstr, modify, (strlen(modify) - strlen(string)));
You are modifying the pointer, not what the pointer points to.
When you pass in path
to TrimVal. It will pass in the memory location of path
e.g. 0x12345
When you do the modify =
you are saying, change the local variable modify
to be a new memory location, e.g. 0x54321
When you return to main, it only has a pointer to 0x12345, and when it looks there, nothing has changed.
You can easily fix your problem by doing
{
...
TrimVal(&path, "*.*", newstr);
...
}
void TrimVal(char** modify, char* string, char* newstr)
{
newstr[0] = '\0';
*modify = strncat(newstr, *modify, (strlen(*modify) - strlen(string)));
return;
}
void TrimVal(char* modify, char* string, char* newstr)
Changing the values of modify
, string
, or newstr
inside the TrimVal()
function has no effect on the variables at the calling function.
Changing the contents of modify
, string
, or newstr
inside the TrimVal()
function will be reflected on the variables at the calling function.
So
void TrimVal(char* modify, char* string, char* newstr)
{
newstr[0] = '\0'; /* will be reflected in the calling function */
modify = "a new string"; /* won't be reflected */
}
I think your function, with a little clearing of code, could do what you want.
Oh ... and you have a memory leak with the path
variable: you malloc some space for it and immediately afterwards lose the address of that space by assigning a different value to the path
variable.
A couple of points in addition to the many other good ones raised in this thread:
LPSTR path = (char*)malloc(strlen(START_PATH));
If this is C, you should not cast the return value of malloc
. (See C FAQ 7.7b.
More importantly, strlen
does not include the terminating \0
in its calculation. So, the memory path
points to is one character short of the required amount of memory to hold START_PATH
plus the \0
. Therefore:
strcpy(path, START_PATH);
invokes undefined behavior by writing one past the memory pointed to by path
.
If you expect your char* variable to be modified in the function and you want to pass by reference, you need to pass it as char* . Remember, you are passing the pointer by reference, so there needs to be an extra layer of indirection (passing char does pass something by reference - a single character!)
I see a problem with the first two statements. You are declaring path as a pointer char and allocating memory for it that is stored in this address holder. In your next statement, you are changing the value in path, pointing it to the start of your char array, START_PATH. The memory you allocated is now lost.
Also, strncat does not call malloc to concatenate. It is expected that you are passing in a buffer large enough to hold the concat, and this is a potential security risk (buffer overrun).
Just one comment about your style of casting the return type of the malloc call. When casting this can hide errors.
This would be a much better style.
Include the stdlib.h and try and make the call to malloc as type independent.
char *ptr_char = NULL;
ptr_char = malloc(sizeof(*ptr_char));
Hope this helps,
C doesn't really have a pass-by-reference. What you are doing here is passing pointers by value. A string in C is represented by a pointer to char. So in the function TrimVal you can modify the contents of the string (that is, the pointed-to data), but not the pointer itself.
strncat modifies the contents of the first parameter and returns the same value.
If you want to change the value of path within TrimVal, you should pass a pointer to a pointer, like so:
...
TrimVal(path, "*.*", newstr);
...
void TrimVal(char** modify, char* string, char* newstr)
{
newstr[0] = '\0';
*modify = strncat(newstr, *modify, (strlen(*modify) - strlen(string)));
return;
}
精彩评论