I would like to have a "dofor" macro which would use
either a suplied loop variable or a default loop variable (f).
dofor(512, i) // should be expanded to
for (i = 512; i != 0; i--)
dofor(512) // should be expanded to
for (f = 512; f != 0; f--)
Could someone give me some pointers here?
|
|
0
|
|
|
|
Reply
|
aleksa
|
11/14/2010 11:08:57 AM |
|
On Nov 14, 6:08=A0am, "aleksa" <aleks...@gmail.com> wrote:
> I would like to have a "dofor" macro which would use
> either a suplied loop variable or a default loop variable (f).
>
> dofor(512, i) // should be expanded to
> for (i =3D 512; i !=3D 0; i--)
>
> dofor(512) // should be expanded to
> for (f =3D 512; f !=3D 0; f--)
>
> Could someone give me some pointers here?
Good preprocessor question, but I'd like to just step in here and say:
"Don't write code like this."
Replacing single statements with macros is a surefire way to make your
code completely unmaintainable. Don't do it if you have any hope of
working on it long term.
Tom
|
|
0
|
|
|
|
Reply
|
Tom
|
11/14/2010 12:24:57 PM
|
|
"aleksa" <aleksazr@gmail.com> writes:
>dofor(512, i) // should be expanded to
>for (i = 512; i != 0; i--)
>dofor(512) // should be expanded to
>for (f = 512; f != 0; f--)
I does not work as follows,
but maybe someone can improve on this?
#define test(x) \
0/x/2; printf( "%s\n", #x ); if( 0 )\
+printf( "f\n" );
The idea is that with �test(i)�, this expands to
0/i/2; printf( "%s\n", "i" ); if( 0 )
+printf( "f\n" );
i.e., effectively,
printf( "%s\n", "i" );
, which should print the line �i�, while �test()�
expands to
0//2; printf( "%s\n", "i" ); if( 0 )
+printf( "f\n" );
, effectively,
0+printf( "f\n" );
, which should print the line �f�. However, it seems
that the �/� do not form a single �//� token this way.
|
|
0
|
|
|
|
Reply
|
ram
|
11/14/2010 12:39:00 PM
|
|
On 11/14/2010 7:39 AM, Stefan Ram wrote:
> "aleksa"<aleksazr@gmail.com> writes:
>> dofor(512, i) // should be expanded to
>> for (i = 512; i != 0; i--)
>> dofor(512) // should be expanded to
>> for (f = 512; f != 0; f--)
>
> I does not work as follows,
> but maybe someone can improve on this?
>
> #define test(x) \
> 0/x/2; printf( "%s\n", #x ); if( 0 )\
> +printf( "f\n" );
>
> The idea is that with �test(i)�, this expands to
>
> 0/i/2; printf( "%s\n", "i" ); if( 0 )
> +printf( "f\n" );
>
> i.e., effectively,
>
> printf( "%s\n", "i" );
>
> , which should print the line �i�, while �test()�
> expands to
>
> 0//2; printf( "%s\n", "i" ); if( 0 )
> +printf( "f\n" );
>
> , effectively,
>
> 0+printf( "f\n" );
>
> , which should print the line �f�. However, it seems
> that the �/� do not form a single �//� token this way.
Right, because comments are recognized and removed in phase 3,
before the preprocessor does its work in phase 4. See section 5.1.1.2
"Translation phases."
--
Eric Sosman
esosman@ieee-dot-org.invalid
|
|
0
|
|
|
|
Reply
|
Eric
|
11/14/2010 1:32:39 PM
|
|
On 2010-11-14, aleksa <aleksazr@gmail.com> wrote:
> I would like to have a "dofor" macro which would use
> either a suplied loop variable or a default loop variable (f).
>
> dofor(512, i) // should be expanded to
> for (i = 512; i != 0; i--)
>
> dofor(512) // should be expanded to
> for (f = 512; f != 0; f--)
>
> Could someone give me some pointers here?
You can't do optional-argument macros.
Furthermore, don't do this. Several reasons, not the least of which is
that you're counting backwards which will usually surprise people, and
you should never hide simple basic syntax behind macros.
-s
--
Copyright 2010, all wrongs reversed. Peter Seebach / usenet-nospam@seebs.net
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
I am not speaking for my employer, although they do rent some of my opinions.
|
|
0
|
|
|
|
Reply
|
Seebs
|
11/14/2010 8:29:56 PM
|
|
Seebs <usenet-nospam@seebs.net> writes:
> On 2010-11-14, aleksa <aleksazr@gmail.com> wrote:
>> I would like to have a "dofor" macro which would use
>> either a suplied loop variable or a default loop variable (f).
>>
>> dofor(512, i) // should be expanded to
>> for (i = 512; i != 0; i--)
>>
>> dofor(512) // should be expanded to
>> for (f = 512; f != 0; f--)
>>
>> Could someone give me some pointers here?
>
> You can't do optional-argument macros.
>
> Furthermore, don't do this. Several reasons, not the least of which is
> that you're counting backwards which will usually surprise people, and
> you should never hide simple basic syntax behind macros.
C99 added variadic macros. You *might* be able to do something like:
#define dofor(count, ...) /* something */
so at least both dofor(512, i) and dofor(512) would be legal. But I
can't think of a way to make this work for what the OP is asking about
(not that I tried very hard).
To the OP: If you're going to do this, at least use all-caps for the
macro name. (The convention of using all-caps for macro names is
intended to make them stand out, so it's obvious to the reader that
something strange is going on.)
For that matter, there's not that much benefit in using a single name
for both. If you want the loop variable name to default to i (yours
defaults to f, but i makes more sense), you could just write:
#define DOFOR(count, var) for ((var) = (count); (var) != 0; (var)--)
#define DOFORI(count) for (i = (count); i != 0; i--)
Or, if you can depend on having a C99 compiler, or at least one that
supports declarations in for loops as an extension:
#define DOFOR(count, var) for (int var = (count); (var) != 0; (var)--)
#define DOFORI(count) for (int i = (count); i != 0; i--)
You have to know how many arguments you're using when you write the
call; using distinct names isn't much of an added burden.
But these are all improvements on a bad idea. A better solution is
just to write ordinary for loops; they're going to be much more
legible to anyone reading your code (including you six months
from now).
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
|
|
0
|
|
|
|
Reply
|
Keith
|
11/14/2010 9:13:59 PM
|
|
aleksa <aleksazr@gmail.com> wrote:
> I would like to have a "dofor" macro which would use
> either a suplied loop variable or a default loop variable (f).
> dofor(512, i) // should be expanded to
> for (i = 512; i != 0; i--)
> dofor(512) // should be expanded to
> for (f = 512; f != 0; f--)
> Could someone give me some pointers here?
This is an easy case.
#define dofor2(n, x, ...) for (x = n; x != 0; x--)
#define dofor(...) dofor2(__VA_ARGS__, f)
The hard case is doing it when you want the first or intermediate parameter
to be optional. But this is possible, too.
#define NARG_(_8, _7, _6, _5, _4, _3, _2, _1, N, ...) N
#define NARG(...) NARG_(__VA_ARGS__, 8, 7, 6, 5, 4, 3, 2, 1)
#define PASTE(a, b) a ## b
#define XPASTE(a, b) PASTE(a, b)
#define CALL(F, ...) F(__VA_ARGS__)
#define OVERLOAD(F, ...) CALL(XPASTE(F, NARG(__VA_ARGS__)), __VA_ARGS__)
#define dofor2(x, n) for (x = n; x != 0; x--)
#define dofor1(n) for (i = n; i != 0; i--)
#define dofor(...) OVERLOAD(dofor, __VA_ARGS__)
This requires C99, but only C99. The NARG macro was posted on comp.lang.c
years ago by Laurent Deniau. All the other tricks just flow naturally from
it.
|
|
0
|
|
|
|
Reply
|
William
|
11/14/2010 9:29:28 PM
|
|
Keith Thompson <kst-u@mib.org> wrote:
> Seebs <usenet-nospam@seebs.net> writes:
> > On 2010-11-14, aleksa <aleksazr@gmail.com> wrote:
> >> I would like to have a "dofor" macro which would use
> >> either a suplied loop variable or a default loop variable (f).
<snip>
> But these are all improvements on a bad idea. A better solution is
> just to write ordinary for loops; they're going to be much more
> legible to anyone reading your code (including you six months
> from now).
For simple loops I completely agree. Most anything that obscures the
underlying syntax or representation is generally a poor idea. Using
unadorned struct types is another example of this rule of thumb. But I've
used this trick for simplifying iterators, and the exception is similar to
when you might typedef a struct--when you really do want to obscure the
syntax.
A very common pattern I use in my code for an iterator looks something like:
foo_foreach([element pointer], [object], [select criteria])
For example:
struct dns_packet *pkt;
struct dns_rr rr;
dns_rr_foreach(&rr, pkt, .type = DNS_T_AAAA, .name = "foo.com.") {
dns_rr_dump(&rr, pkt, stdout);
}
or
struct rtcp_packet *pkt;
union rtcp_any *any;
rtcp_foreach(&any, pkt, .type = RTCP_SDES) {
struct sdes_item item;
sdes_foreach(&item, &any->sdes) {
sdes_dump(&item, stdout);
}
}
Of course, the "magic" macros use well-defined interfaces which can be used
directly; typically a single function (foo_grep()) which takes an explicit
iteration state--initialized with selection criteria--along with the other
element and object pointers. I do this because (a) composability should be
baked in as much as practical; and (b) I often need iterators that can be
interrupted.
FWIW, the foreach macros also make use of C99 compound literals and for loop
declarations in addition to __VA_ARGS__ tricks--which isn't evident here but
is used for initializing the compound literal.
|
|
0
|
|
|
|
Reply
|
William
|
11/14/2010 10:17:19 PM
|
|
|
7 Replies
177 Views
(page loaded in 0.102 seconds)
Similiar Articles: Macro not resoved - comp.soft-sys.sasMacro not resoved - comp.soft-sys.sas WARNING: Apparent symbolic reference P not resolved. - comp.soft ... Confidence ... Macro with a default value - comp.lang.c WARNING ... API: Delete all custom properties - comp.cad.solidworks... found several examples of how to do this but none seem to work, I need a macro ... Default value is "". '@param emptyonly Optional. Boolean. Default value is False ... How to change Default Page Setup settings? Please help - comp.cad ...Hi everyone I need to change the default Page Setup ... 2005 Viewer, which has shared regedit page setup values ... You'd have to have a macro that goes through all the ... How to encode an unconditional jump in 64-bit mode? - comp.lang ...Then define a macro like this %macro JUMP 2 db 0eah dw %1 ;base dw %2 ... ret In 64-bit mode you can only push and pop 64-bit and 16-bit values because the default ... Macro to send the alert message on ping failure - comp.sys.tandem ...It does not say what the default is for the number of packets sent if you ... Make sure that the value of host in your macro really is the n.n.n.n that you passed as the ... WARNING: Apparent symbolic reference P not resolved. - comp.soft ...Macro not resoved - comp.soft-sys.sas WARNING: Apparent symbolic reference P not resolved. - comp.soft ... Confidence ... Macro with a default value - comp.lang.c WARNING ... Suppress Logout output of OPTIONS NOMPRINT; - comp.soft-sys.sas ...Because all my macros call the > options save and I don ... For instance, to save option values, the log looks like ... terminate) command - comp.unix.solaris... to /etc/default ... How to update K-Factor through API - comp.cad.solidworks ...The value for swCustBend.KFactor is updated, but not the ... As Double ' Rollback to change default ... rebuilding Not through the API, but after the macro ... Floating Point and printf() - comp.lang.asm.x86... even using printf() correctly with floating point values. ... Microsoft (R) Macro Assembler Version 5.10A.01 Jul 22 ... These are called the default argument promotions. solving a "ActiveX component can't create object or return ...... accdb database, run the below code as a macro and it ... in a document, populate a recordset with the values ... to each other): http://support.microsoft.com/default ... Tips:Setting Default Values for Macro Parameters - sasCommunityQuite often it is necessary to set a default value for a macro parameter that is passed to a program. If the program is a macro, the %IF statement can be used to ... IBM Using Default Values in a Prompt Macro - Report Studio ...When a default value is defined in a prompt macro configured in Framework Manager, how does it function in a Report Studio report? 7/21/2012 5:46:14 PM
|