Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > Preprocessor - can it make conditional decisions

Reply
Thread Tools

Preprocessor - can it make conditional decisions

 
 
Thad Smith
Guest
Posts: n/a
 
      08-11-2007
Richard Tobin wrote:
> In article <(E-Mail Removed). com>,
> <(E-Mail Removed)> wrote:
>
>>Can the proprocessor make conditional decisions. Here's an example of
>>the functionality (not standard C!)
>>
>>#define PUT_BYTE(const_index, val) \
>>#preprocessor_if (const_index == 0) \
>> ({ *(77) = (val); }) \
>>#preprocessor_else_if (const_index == 1) \
>> ({ *(99) = (val); }) \
>>#preprocessor_end

>
>
> No. But in this particular case, if you just use an ordinary "if",
> the compiler will be able to see that the condition is constant and
> will probably generate the same code as if you had been able to do it
> in the preprocessor. On the other hand, it may well give a warning
> for a conditional with a constant condition.


I think that answers the OP well.

I use that technique a fair amount in embedded systems to generalize I/O
port, pin, logic level, shadow RAM requirements, etc. The compiler
evaluates a lot of constant conditionals and expressions, then generates
efficient code. The only bane is the additional warning you mention and
the difficulty of reading some of the hairy macros. To compensate,
their use is well documented.

--
Thad
 
Reply With Quote
 
 
 
 
Army1987
Guest
Posts: n/a
 
      08-11-2007
On Fri, 10 Aug 2007 19:18:55 -0500, Stephen Sprunk wrote:

> <(E-Mail Removed)> wrote in message
> news:(E-Mail Removed) ups.com...
>> Hello!
>>
>> Can the proprocessor make conditional decisions. Here's an example of
>> the functionality (not standard C!)
>>
>> #define PUT_BYTE(const_index, val) \
>> #preprocessor_if (const_index == 0) \
>> ({ *(77) = (val); }) \
>> #preprocessor_else_if (const_index == 1) \
>> ({ *(99) = (val); }) \
>> #preprocessor_end
>>
>> Could the above snipped be done in C??

>
> Yes. The C way to do the above is:
>
> #define PUT_BYTE(const_index, val) \
> do { \
> if (!const_index) { *(int*)77 = (val); } \
> else { *(int *)99 = (val); } \
> } while (0)


Any reasons for use the ugly do while (0) trick when there is
a way to write it as an expression? What if I want to use it
as the third expression in the guard of a for loop? IMO, this
(except when necessary) is even worse than using a function.

#define PUT_BYTE(const_index, val) \
( *(int *)((const_index) ? 99 : 77) = (val) )
(Note that it always evaluates each argument exactly once.)
Or
int PUT_BYTE(int const_index, int val)
{
if (const_index) {
return *(int *)99 = val;
} else {
return *(int *)77 = val;
}
> Of course, there's no need to use a macro in the first place; just make
> it a function. In C99 (or various flavors of C89 with the extension),
> you may want to make it an inline function if you're concerned about
> overhead.

Right.
--
Army1987 (Replace "NOSPAM" with "email")
No-one ever won a game by resigning. -- S. Tartakower

 
Reply With Quote
 
 
 
 
Army1987
Guest
Posts: n/a
 
      08-11-2007
On Fri, 10 Aug 2007 10:06:59 -0400, CBFalconer wrote:

> http://www.velocityreviews.com/forums/(E-Mail Removed) wrote:
>>
>> Can the proprocessor make conditional decisions. Here's an example
>> of the functionality (not standard C!)
>>
>> #define PUT_BYTE(const_index, val) \
>> #preprocessor_if (const_index == 0) \
>> ({ *(77) = (val); }) \
>> #preprocessor_else_if (const_index == 1) \
>> ({ *(99) = (val); }) \
>> #preprocessor_end
>>
>> Could the above snipped be done in C??

>
> Works better if you use the language correctly:
>
> #if const_index == 0
> # define PUT_BYTE(const_index, val) (whatever is legal)
> #elsif const_index == 1

You meant elif?
> # define PUT_BYTE(const_index, val) (something else)

Hmm. If const_index is a macro expanding to 1, the above becomes
# define PUT_BYTE(0, val) (something else)
> #endif
>

I think the OP was trying to have a macro in which
PUT_BYTE(0, val) expanded to ((something)(val))
and PUT_BYTE(1, foo) expanded to ((sth_else)(foo))
I don't think it is possible in standard C, but, since the first
argument is known at preprocessing time, one could simplily use
a PUT_BYTE0 macro and a PUT_BYTE1 macro.

--
Army1987 (Replace "NOSPAM" with "email")
No-one ever won a game by resigning. -- S. Tartakower

 
Reply With Quote
 
Army1987
Guest
Posts: n/a
 
      08-11-2007
On Fri, 10 Aug 2007 16:13:42 +0000, anon.asdf wrote:

> On Aug 10, 3:09 pm, Chris Dollin <(E-Mail Removed)> wrote:
>>
>> (a) When did `({ *((int *)99) = (val); })` become legal syntax (fx:etc)?
>>

>
> Hi Chris!
>
> Here's a nice example that illustrates ({ ... }):
>
>
> /*********({ ... })**********/
> #include <stdio.h>
>
> #define GET_OUT 'q'
>
> #define PRE_COND \
> ({ c = getchar(); \
> putchar(c); \
> })

This is not standard C, it is a GNU extension. Try
#define PRE_COND (c = getchar(), putchar(c))

--
Army1987 (Replace "NOSPAM" with "email")
No-one ever won a game by resigning. -- S. Tartakower

 
Reply With Quote
 
Marcin Wolcendorf
Guest
Posts: n/a
 
      08-11-2007
Army1987 <(E-Mail Removed)> wrote:
> On Fri, 10 Aug 2007 10:06:59 -0400, CBFalconer wrote:
>
> > (E-Mail Removed) wrote:
> >>
> >> Can the proprocessor make conditional decisions. Here's an example
> >> of the functionality (not standard C!)
> >>
> >> #define PUT_BYTE(const_index, val) \
> >> #preprocessor_if (const_index == 0) \
> >> ({ *(77) = (val); }) \
> >> #preprocessor_else_if (const_index == 1) \
> >> ({ *(99) = (val); }) \
> >> #preprocessor_end
> >>
> >> Could the above snipped be done in C??

> >
> > Works better if you use the language correctly:
> >
> > #if const_index == 0
> > # define PUT_BYTE(const_index, val) (whatever is legal)
> > #elsif const_index == 1

> You meant elif?
> > # define PUT_BYTE(const_index, val) (something else)

> Hmm. If const_index is a macro expanding to 1, the above becomes
> # define PUT_BYTE(0, val) (something else)
> > #endif
> >

> I think the OP was trying to have a macro in which
> PUT_BYTE(0, val) expanded to ((something)(val))
> and PUT_BYTE(1, foo) expanded to ((sth_else)(foo))
> I don't think it is possible in standard C,


Consider ## operator. It *is* possible. And you don't really want to do
it... .

Let's *try* to do it:
#define PUT_BYTE_0 sth
#define PUT_BYTE_1 sth_else

#define PUT_BYTE_EXPANDED(__x, __y) \
((PUT_BYTE_ ## __x)(__y))

#define PUT_BYTE(__x, __y) PUT_BYTE_EXPANDED(__x, __y)


> but, since the first
> argument is known at preprocessing time, one could simplily use
> a PUT_BYTE0 macro and a PUT_BYTE1 macro.


Sometimes you can't. Consider function with parameter in it's name (you
can't use parameter, cause you have no register available) configured at
compile time.

M.

PS. I leave discovering PUT_BYTE_EXPANDED usage reasons as an exercise .
M.
 
Reply With Quote
 
Richard
Guest
Posts: n/a
 
      08-11-2007
CBFalconer <(E-Mail Removed)> writes:

> Ravishankar S wrote:
>>
>> Assuming val is of type byte only, perhaps you can use inline functions..

>
> You are top-posting. Cease this if you want to have answers.
>
> Please do not top-post. Your answer belongs after (or intermixed
> with) the quoted material to which you reply, after snipping all
> irrelevant material. See the following links:
>
> --
> <http://www.catb.org/~esr/faqs/smart-questions.html>
> <http://www.caliburn.nl/topposting.html>
> <http://www.netmeister.org/news/learn2quote.html>
> <http://cfaj.freeshell.org/google/> (taming google)
> <http://members.fortunecity.com/nnqweb/> (newusers)


Back in the killfile you go. And get your signatures sorted out before
you lecture other people on posting styles.
 
Reply With Quote
 
Stephen Sprunk
Guest
Posts: n/a
 
      08-11-2007
"Army1987" <(E-Mail Removed)> wrote in message
news(E-Mail Removed)...
> On Fri, 10 Aug 2007 19:18:55 -0500, Stephen Sprunk wrote:
>> Yes. The C way to do the above is:
>>
>> #define PUT_BYTE(const_index, val) \
>> do { \
>> if (!const_index) { *(int*)77 = (val); } \
>> else { *(int *)99 = (val); } \
>> } while (0)

>
> Any reasons for use the ugly do while (0) trick when there is
> a way to write it as an expression? What if I want to use it
> as the third expression in the guard of a for loop? IMO, this
> (except when necessary) is even worse than using a function.
>
> #define PUT_BYTE(const_index, val) \
> ( *(int *)((const_index) ? 99 : 77) = (val) )


It didn't occur to me to use the trinary operator on the left side of an
assignment expression; that's probably an improvement, though I consider it
less readable and you should end up with the same code generated.

> (Note that it always evaluates each argument exactly once.)


It's better in that respect.

> Or
> int PUT_BYTE(int const_index, int val)
> {
> if (const_index) {
> return *(int *)99 = val;
> } else {
> return *(int *)77 = val;
> }


Evil; functions should not be in upper case.

S

--
Stephen Sprunk "Those people who think they know everything
CCIE #3723 are a great annoyance to those of us who do."
K5SSS --Isaac Asimov


--
Posted via a free Usenet account from http://www.teranews.com

 
Reply With Quote
 
anon.asdf@gmail.com
Guest
Posts: n/a
 
      08-12-2007
On 11 Aug., 13:09, Marcin Wolcendorf <(E-Mail Removed)> wrote:
....
>
> Consider ## operator. It *is* possible. And you don't really want to do
> it... .
>
> Let's *try* to do it:
> #define PUT_BYTE_0 sth
> #define PUT_BYTE_1 sth_else
>
> #define PUT_BYTE_EXPANDED(__x, __y) \
> ((PUT_BYTE_ ## __x)(__y))
>
> #define PUT_BYTE(__x, __y) PUT_BYTE_EXPANDED(__x, __y)
>
> > but, since the first
> > argument is known at preprocessing time, one could simplily use
> > a PUT_BYTE0 macro and a PUT_BYTE1 macro.

>
> Sometimes you can't. Consider function with parameter in it's name (you
> can't use parameter, cause you have no register available) configured at
> compile time.
>
> M.
>
> PS. I leave discovering PUT_BYTE_EXPANDED usage reasons as an exercise .
> M.


Hi Marcin!

I've tested it with
/*************/
#include <stdio.h>

#define PUT_BYTE_0(val) printf("0: %d\n", val)
#define PUT_BYTE_1(val) printf("1: %d\n", val)

#define PUT_BYTE(__x, __y) (PUT_BYTE_ ## __x(__y))

int main(void)
{
PUT_BYTE(0, ;
PUT_BYTE(1, 9);
return 0;
}
/*************/

and it works nicely:

(I don't think we need PUT_BYTE_EXPANDED)

But this is just luck, that it's such a simple example!


How would you do the following:


/************** Example: nice to have *****************/
int regA;
#define MEM_MAP_A &regA;

int regB;
#define MEM_MAP_B &regB;

#define GO(val) \
#preprocessor_META_level_ON \
if (!(val % 3)) \
#machine_code_begin \
*((int *) MEM_MAP_A) = val \
#machine_code_end \
else \
#machine_code_begin \
*((int *) MEM_MAP_B) = val \
#machine_code_end \
#preprocessor_META_level_OFF \

/*
if the preprocessor catches a variable in the meta_level e.g.
{
int my_var;
GO(my_var);
}

then a compiler-error (or rather preprocessor-error) should result!
*/

//In the code I'll have:

{
GO(1);
//...
GO(876);
//...
GO(7987);
//...
GO(3);
//...

}

/************** end *****************/

????????????


It can probably be done, but the header file with it's preprocessor
lines will be huge. Probably just as huge as

/************** Example: bitter reality *****************/
//...
#define GO_1 *((int *) MEM_MAP_B) = 1
#define GO_2 *((int *) MEM_MAP_B) = 2
#define GO_3 *((int *) MEM_MAP_A) = 3
#define GO_4 *((int *) MEM_MAP_B) = 4
#define GO_5 *((int *) MEM_MAP_B) = 5
//...
#define GO_7987 *((int *) MEM_MAP_B) = 7987

//many many lines above!

//In the code I'll have:

{
GO_1;
//...
GO_876;
//...
GO_7987;
//...
GO_3;
//...

}

/************** end *****************/


The reality is that the preprocessor is not turing complete if a
program is preprocessed only once. (Ref: http://www.ioccc.org/2001/herrmann1.hint)

But a Meta-Level would make it turing complete, right? Refer to:
http://groups.google.de/group/comp.l...4e79644f7befd?

-Albert

 
Reply With Quote
 
Army1987
Guest
Posts: n/a
 
      08-12-2007
On Sun, 12 Aug 2007 05:31:19 -0700, anon.asdf wrote:
> The reality is that the preprocessor is not turing complete if a
> program is preprocessed only once. (Ref: http://www.ioccc.org/2001/herrmann1.hint)
>
> But a Meta-Level would make it turing complete, right? Refer to:
> http://groups.google.de/group/comp.l...4e79644f7befd?
>

That's what the compiler is for.
--
Army1987 (Replace "NOSPAM" with "email")
No-one ever won a game by resigning. -- S. Tartakower

 
Reply With Quote
 
anon.asdf@gmail.com
Guest
Posts: n/a
 
      08-12-2007
On Aug 12, 2:39 pm, Army1987 <(E-Mail Removed)> wrote:
> On Sun, 12 Aug 2007 05:31:19 -0700, anon.asdf wrote:
> > The reality is that the preprocessor is not turing complete if a
> > program is preprocessed only once. (Ref:http://www.ioccc.org/2001/herrmann1.hint)

>
> > But a Meta-Level would make it turing complete, right? Refer to:
> >http://groups.google.de/group/comp.l...4e79644f7befd?

>
> That's what the compiler is for.
> --
> Army1987 (Replace "NOSPAM" with "email")
> No-one ever won a game by resigning. -- S. Tartakower


No! The compiler is there to generate machine code from C.

It should not be clouded by Meta-information like bit-width
calculations etc. all of which belong firmly to the preprocessor.

Though nice things can be done with the preprocessor, it is
unfortunately not powerful enough to allow one to really do things on
a meta-level.

Things like bit-width calculations etc. should really be done on a
Meta-Level, since the output is then a fixed bit-width, or a fixed C-
code segment:

I hate writing things like:

#define AAA 1<<8

int a = AAA;

because how do I know what the compiler is going to do, without
checking the generated asm, or machine code?

I'll rather write:
#define AAA 256 /* 1<<8 */

but I don't like it. This is where a Meta-Level would come in handy:

#define AAA \
#META_level( 1<<8 )

//or

#define BIT_WIDTH 8
#define AAA \
#META_level( 1<<BIT_WIDTH )

The Meta-Level guarantees that this is resolved.

On the otherhand, perhaps I've now just written a lot of junk, since
perhaps every compiler out there will simplify and resolve constants,
constant expressions, conditionals with constants, etc.

I still think my modulo-3 example:
http://groups.google.com/group/comp....9a3452cb74c4c?
is interesting though.

?
-Albert

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Decisions, Decisions.... Max Burke NZ Computing 25 09-24-2006 05:58 AM
Can html perform interactively or make decisions? senhortomas@hotmail.com HTML 15 02-28-2006 05:09 PM
Decisions, decisions... Waterspider Digital Photography 8 12-28-2005 09:48 PM
Decisions Decisions Larry Digital Photography 4 06-28-2005 03:41 PM
Scripts for helping you to make decisions rdsteph@mac.com Javascript 0 03-28-2005 03:43 PM



Advertisments