Reputation:
Disclaimer: This question is strictly academic. The example I'm about to give is probably bad style.
Suppose in C I write a subroutine of this form:
char *foo(int x)
{
static char bar[9];
if(x == 0)
strcpy(bar, "zero");
else
strcpy(bar, "not zero"),
return bar;
}
Then, elsewhere, I use foo
as follows:
printf("%i is %s\n", 5, foo(5));
My mental model of pointers and static variables predicts that, in practice, the output of this printf will be
5 is not zero
...but is this actually required by the C standard, or am I in nasal demon territory?
To make things even worse, what about something like
strcpy(foo(5), "five");
My mental model says this should "work" unless it's explicitly illegal, though it's somewhat pointless since it doesn't affect the output of foo
. But again, is this actually defined by the standard?
Upvotes: 13
Views: 836
Reputation: 7640
Nothing wrong with it. Better style will be
const char *foo(int x);
Then you can't strcpy into it without casting away the const. If you really want to break it nothing can stop you.
if you want to make it re-entrant.
const char *foo(int x)
{
return (x? "not zero" : "zero");
}
Upvotes: 0
Reputation: 127538
I see nothing wrong with this code whatsoever.
The pointer that foo()
returns is a valid pointer and you're allowed to dereference it.
Edit: By "nothing wrong" I mean that everything is syntactically ok, but I agree with other answers that this code is not good in any meaning of the word for a variety of reasons. It is merely correct according to the C standard.
Upvotes: 0
Reputation: 754450
What you've written is OK; there are no nasal demons awaiting you. Even the strcpy()
example is 'OK' because you are not trampling beyond the bounds of the array. That 'OK' is in quotes because it is not a good idea, but as written, there is no out of bounds memory access and so no undefined behaviour. The static
data in the function is there throughout the program's lifetime, containing the last value that was written to it.
There could be problems if you try:
printf("%i is %s but %i is %s\n", 5, foo(5), 0, foo(0));
You will get the wrong answer for one of the two numbers, but it is not defined which will be the wrong answer.
Upvotes: 11
Reputation: 477348
Under any condition, foo()
returns a pointer to a static variable, whose lifetime is permanent (i.e. it lives from when control passes over it for the first time until the end of the program). This is perfectly fine.
The logic of your code is less fine; for instance, the function is not re-entrant and far from thread-safe, and of course the unguarded string operation is outright suicide.
Upvotes: 1
Reputation: 182664
Well, since you want a quote from the standard:
The lifetime of an object is the portion of program execution during which storage is guaranteed to be reserved for it.
An object whose identifier is declared without the storage-class specifier _Thread_local, and either with external or internal linkage or with the storage-class specifier static, has static storage duration. Its lifetime is the entire execution of the program and its stored value is initialized only once, prior to program startup.
Upvotes: 4