Is it correct to return const char *
from a function when the actual buffer being returned is not a constant array?
For example, in this minimal example below, buffer
is a non-const char *
but then it is returned as const char *
.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
const char *str_alloc(const char *str, size_t n)
{
char *buffer;
if ((buffer = malloc(n)) != NULL) {
memcpy(buffer, str, n);
}
return buffer;
}
int main()
{
const char *str = str_alloc("hello", 6);
if (str == NULL) {
fprintf(stderr, "memory allocation error\n");
return EXIT_FAILURE;
}
printf("str: %s\n", str);
// str[0] = 'H'; // error: read-only variable is not assignable
free((void *) str);
return 0;
}
In the above example, returning a non-const char *buffer
as const char *
helps me to enforce that the caller cannot modify the content of the buffer without an explicit type cast. But I would like to know if this is well-defined code or if this code invokes undefined behaviour due to treating char *
as const char *
?
This is well defined code since you restrict the usage possibility of the value. As the saying goes "who can do more, can do less". The opposit would not be valid and would require an explicit cast.
But there is a problem with your code. Passing the size of the string as argument is unsafe. In your example, you won’t copy the '\0' in the allocated buffer. As a consequence, the string is not properly terminated. The behavior of your program is undefined and could end in a segmentation fault because the printf
would try to access data beyond the end of the buffer.
It would be preferable that the length of the string is determined in the str_alloc
function.