There are two problems with encapsulating that version in my LOOP_OVER_ALL_ELEPHANTS macro. One is that it contains two separate statements, so it breaks syntactic indivisibility in cases like
if (condition)
LOOP_OVER_ALL_ELEPHANTS(elephant) {
/* ... */
}
Admittedly you might reasonably feel that I should just avoid calling the macro in any circumstances like that, which would be a fair enough position, but I note that all the other expansions discussed here (including the evil switch one) do work in that context.
But the other, more important, reason is that it has a declaration in it, and in C90 declarations can't be interleaved with code. (For annoying reasons, the code in which I was using this macro is required to compile cleanly in C90 as well as C99.) So if I put any other statement before calling LOOP_OVER_ALL_ELEPHANTS, the declaration of specialfirsttimeflag would become illegal.
I was trying an alternative solution. I think you may be able to fix the problems this approach has with not quite being semantically identical to a "for" block, but I couldn't overcome the restrictions on not being able to declare another variable.
You could possibly wrap up the "compare elephant and head, except the first time, then just return true" logic into a function with a static variable in, but it would mean the code would be definitely non-reentrant. (Unless your preprocessor did something clever with the LINE directive in the macro, but I can't remember, that wasn't in C90 either, right?)
No, __LINE__ is perfectly good C90. (Or else I wouldn't have used it in my coroutines trick – my original invention of that predated C99 by several years, and Tom Duff said he'd thought of the same thing much, much earlier.)
I don't see how it helps you here, though. It surely can't save you from thread-safety issues, because it won't have a distinct value in each thread?
Thank you. I don't think I quite thought through what i did want. But i think that where I'm going is that if you want to use a function to represent the "compare el against head, except ignore the first and every second match" logic instead of a simple local var, it needs to identify when its part of the same loop and when it isn't, which it might be able to do with a combination of (a) using some thead local storage or thread id to maintain when the next call is from the same thread and (b) using a line directive to determine when its called from different (nested) places in the same file and thread.
Your solution is probably right because it uses syntax to resolve a problem with insufficiently expressive syntax. Whereas mine (if it worked) would be how to solve a problem if the constraints here were logical parts of the program for some reason.
I agree it's horrendous, that's why i recommend using a language with convenient local variables, fewer macros, etc, etc :)
int specialfirsttimeflag;
for (elephant = head, specialfirsttimeflag= 1;
elephant != head && specialfirsttimeflag--;
elephant = elephant->next) {
Or you can't because it might conflict with a name outside the macro?
But the other, more important, reason is that it has a declaration in it, and in C90 declarations can't be interleaved with code. (For annoying reasons, the code in which I was using this macro is required to compile cleanly in C90 as well as C99.) So if I put any other statement before calling LOOP_OVER_ALL_ELEPHANTS, the declaration of
specialfirsttimeflag
would become illegal.You could possibly wrap up the "compare elephant and head, except the first time, then just return true" logic into a function with a static variable in, but it would mean the code would be definitely non-reentrant. (Unless your preprocessor did something clever with the LINE directive in the macro, but I can't remember, that wasn't in C90 either, right?)
__LINE__
is perfectly good C90. (Or else I wouldn't have used it in my coroutines trick – my original invention of that predated C99 by several years, and Tom Duff said he'd thought of the same thing much, much earlier.)I don't see how it helps you here, though. It surely can't save you from thread-safety issues, because it won't have a distinct value in each thread?
Thank you. I don't think I quite thought through what i did want. But i think that where I'm going is that if you want to use a function to represent the "compare el against head, except ignore the first and every second match" logic instead of a simple local var, it needs to identify when its part of the same loop and when it isn't, which it might be able to do with a combination of (a) using some thead local storage or thread id to maintain when the next call is from the same thread and (b) using a line directive to determine when its called from different (nested) places in the same file and thread.
Your solution is probably right because it uses syntax to resolve a problem with insufficiently expressive syntax. Whereas mine (if it worked) would be how to solve a problem if the constraints here were logical parts of the program for some reason.
I agree it's horrendous, that's why i recommend using a language with convenient local variables, fewer macros, etc, etc :)