In C, string operations cannot have a convenient interface, because of memory management. If a function receives a string, and converts it to another string, you should decide how to declare its interface.
The simplest interface is in-place (strtok
uses it); you can use it only if the output is somehow smaller than input:
void func(char* input_and_output);
A more traditional interface is “output in pre-allocated buffer” (sprintf
uses it); you can use it only if it’s possible to calculate or somehow constrain the size of the output:
void func(const char* input, char* output);
Another idea is “allocate the output dynamically” (asprintf
uses it); it doesn’t have limitations but is harder to use:
char* func(const char* input);
Its disadvantage is the responsibility that it imposes on the caller – it must free
the allocated string at some time in the future.
Let’s use the third interface:
char* transFormPath(const char* filePath)
{
char* newPath;
newPath = malloc(100); // is 100 enough? no idea
strcpy(newPath, "haha"); // just an example
return newPath;
}
int main()
{
...
char* filePath = "path";
char* newPath = transFormPath(filePath);
...
free(newPath);
}
If you decided to use this interface, your transFormPath
function should allocate the string dynamically, and the caller should free the string at some time when it’s not needed anymore. This is not trivial to accomplish – usually the “time when the string is not needed” is not easy to define, and if you change your code, the time when it’s safe to call free
can change without you realizing it. As a quick-and-dirty hack, you can write your code without freeing memory (i.e. introduce a memory leak on purpose).
Let’s use the second interface:
void transFormPath(const char* filePath, char* newPath)
{
// Here we assume newPath has enough space to hold the output
strcpy(newPath, "haha"); // just an example
}
int main()
{
...
char* filePath = "path";
char* newPath = malloc(100); // is 100 enough? no idea
transFormPath(filePath, newPath);
...
free(newPath);
...
char newPath2[100]; // is 100 enough? no idea
transFormPath(filePath, newPath2);
}
A handy rule of thumb is “malloc
and free
should be called in the same function” – this interface makes it possible not to violate it.
Also, this interface makes it possible to use stack (automatic) memory allocation – if there is some limit on the size of the output, just allocate the maximum possible buffer on stack.
1
solved string literal pointer issue passing to nested functions