1

How can I make a function that remembers its returned result?

For example:

char * foo(char * str1, char * str2){
   ...
   return bar;
}

int main(){
  ...
  foo(a,b);   //returns a string
  foo(NULL,c);//will use the returned above string in the NULL parameter
}

This is similar to how strtok works.

I suppose a global variable could work, but as far as I know it isn't good practice, is there another way? Does strtok works with a global variable?

shinzou
  • 5,850
  • 10
  • 60
  • 124

2 Answers2

3

That's what the static keyword in C is for. Kind of! Be wary, see edits below.

A variable with static storage class will exist for the lifetime of the program, not only to the end of the declaring scope:

int foo()
{
    static int counter = 0;
    counter ++;
    return counter;
}

will return 1,2,3... on successive calls.

EDIT: The commentors seem to agree that it'd be wise to warn you that static is dangerous if you're doing concurring access (ie. multi-threading), which I agree. But then again, you're already aware that global variables can be harmful, so this might not be new, and considering the nature of your question, you might not be at the point in your programming carreer where you're doing multi-threading; if you're doing, please refer to whatever introduces you to multi-threading for safe ways of modifying shared states (semaphores/mutexes...).

EDIT2: It's of course not only hazardous in multi-threading environments; for example, when two different functions call foo internally, and expect to see their own sequence of 1,2,3..., things will go wrong. Use with extreme care.

EDIT3: On third though, @sashoalm 's answer is correct and fits the title of your question best. static was more meant for immutable, one-time initializable states, not for modifiable things that can burst into flames in almost any environment. So here I quote the most important line of the best answer here, since you've decided to accept my answer, which could mislead later readers:

So the most correct answer is NO, you cannot do that in C, and no, static is not the answer.

Community
  • 1
  • 1
Marcus Müller
  • 34,677
  • 4
  • 53
  • 94
  • That is a correct answer, but it could do good to mention that a `static` local variable isn't much better than a mutable global: their only difference is scope. `static` locals are limited to the function's scope, which can be handy. They're just as thread-unsafe as mutable globals. –  Feb 22 '15 at 18:09
  • 1
    Or maybe better [`_Thread_local`](http://en.cppreference.com/w/c/language/storage_duration). Depends on use-case. – Deduplicator Feb 22 '15 at 18:09
2

I'm answering your title, which is "How can a function “remember” it's result for its next use?". Your title implies the general case, and I'm not interested in the particular function in your question body.

First, I'd like to say kudos to Python for the yield keyword, unfortunately, in C there is no such syntactic sugar.

So the most correct answer is NO, you cannot do that in C, and no, static is not the answer.

Static is not reentrant. Sometimes a simple no, you cannot do that, not for real, not in C, is better than telling you half-baked solutions. C just doesn't have this feature, and that's it.

Python has yield, C doesn't. The end.

You'll have to simulate it by using a struct to hold the state.

Some pseudo-code:

struct State { ... };
Output foo(struct State *state, ...) { ... }

...

foo(&state);
foo(&state);

If you don't want to do it the right way, then use static and spend 2-3 days figuring out bugs when you try to nest a call to the function. strtok has bitten people that way.

Note that using static might make the function not reentrant. Be careful:

Output foo(...) { static struct State state; ... }

Addendum

Functions in the mathematical sense are by definition stateless. If it has state, then it's an object, not a function. A function with static state is semantically really a singleton object.

State implies memory, and memory + methods = object.

sashoalm
  • 75,001
  • 122
  • 434
  • 781
  • which would definitely *not* let the function remember its own state, but would let the programmer handle it outside; it's very C, and it's basically what inspired people to write C++, and at times it's *extremely* handy, but it's not an answer to not wanting to handle the state as the caller of `foo`. – Marcus Müller Feb 22 '15 at 18:08
  • What do you mean by not reentrant? – shinzou Feb 22 '15 at 18:14
  • @MarcusMüller Well C just doesn't have that feature. `static` only sounds deceptively like what he wants, but it is actually not what he wants and will bite him. It's a fake state because it's a global variable for all practical purposes. It's not reentrant. – sashoalm Feb 22 '15 at 18:14
  • @sashoalm: yep. but it's what he asked for -- I've added a second edit to my answer, hopefully that'll warn him. Also, since your answer is more useful for the afterworld, I recon I should give you my upvote :) – Marcus Müller Feb 22 '15 at 18:19
  • @MarcusMüller I hate questions that disagree between title and body. If the title is generic like "How can a function “remember” it's result for its next use?" I assume the question is just that. I don't really care about his particular function. – sashoalm Feb 22 '15 at 18:22
  • @sashoalm: OP is not being overly constructive in his commenting, either, so I can't blame you. – Marcus Müller Feb 22 '15 at 18:23
  • @MarcusMüller Agreed. Often I come to the site from Google. There's a question with a promising title just like my problem. And then the question body is "why doesn't my code dump work"? – sashoalm Feb 22 '15 at 18:26
  • Why does it have to be a struct? – shinzou Feb 22 '15 at 18:26
  • @sashoalm: you've just been cited ;) – Marcus Müller Feb 22 '15 at 18:31
  • @MarcusMüller I feel like an academic ;) – sashoalm Feb 22 '15 at 18:34