char *str_dup(const char *s)
{
char *result = malloc(strlen(s) + 1);
if (result != NULL) {
strcpy(result, s);
}
return result;
}
#undef strdup
#define strdup(s) str_dup(s)
int main(void)
{
char *s = strdup("hello, world");
if (s == NULL) {
fputs("strdup() failed\n", stderr);
return EXIT_FAILURE;
}
else {
puts(s);
return EXIT_SUCCESS;
}
}
is valid, and that it fails to be strictly conforming only because of
the possibility of failure in the calls to malloc and perhaps puts.
(There's some controversy about whether I/O failures break strict
conformance; I don't want to get into that in this this thread.)
As a matter of style and robust coding, I prefer not to worry about
the details of which identifiers are reserved for which purposes in
which circumstances. It's easier just to avoid all potentially
reserved identifiers in all circumstances than to keep track of all
the rules. Because of that, I wouldn't write the above program in
that way; I'd probably just name the function str_dup or dupstr and
not worry about the macro. (Or I might use strdup if I didn't care
about portability to non-POSIX systems.)
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"