C abuse of the week [entries|reading|network|archive]
simont

[ userinfo | dreamwidth userinfo ]
[ archive | journal archive ]

Thu 2011-03-17 10:23
C abuse of the week
LinkReply
[identity profile] atheorist.livejournal.comThu 2011-03-17 15:07
Do you prefer the switch to a flag like this?

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?
Link Reply to this | Thread
[personal profile] simontThu 2011-03-17 15:19
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.
Link Reply to this | Parent | Thread
[identity profile] cartesiandaemon.livejournal.comThu 2011-03-17 21:13
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?)
Link Reply to this | Parent | Thread
[personal profile] simontFri 2011-03-18 09:12
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?
Link Reply to this | Parent | Thread
[identity profile] cartesiandaemon.livejournal.comFri 2011-03-18 10:48
:)

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 :)
Link Reply to this | Parent
navigation
[ go | Previous Entry | Next Entry ]
[ add | to Memories ]