Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Preprocessor - can it make conditional decisions

2 views
Skip to first unread message

anon...@gmail.com

unread,
Aug 10, 2007, 8:36:24 AM8/10/07
to
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??

-anon.asdf

anon...@gmail.com

unread,
Aug 10, 2007, 8:44:22 AM8/10/07
to

A better title would be:
"Can the proprocessor make conditional decisions in macros, based on
macro arguments"...

sorry about that...

Richard Tobin

unread,
Aug 10, 2007, 8:45:51 AM8/10/07
to
In article <1186749384....@m37g2000prh.googlegroups.com>,
<anon...@gmail.com> 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.

-- Richard


--
"Consideration shall be given to the need for as many as 32 characters
in some alphabets" - X3.4, 1963.

Chris Dollin

unread,
Aug 10, 2007, 8:47:42 AM8/10/07
to
anon...@gmail.com wrote:

No, it can't.

When did `({ *(99) = (val); })` become legal syntax? Is this some C99
thing I missed, or a proprietaryism I've been lucky to escape?

--
Chris "looking nervously over my shoulder" Dollin

Hewlett-Packard Limited registered office: Cain Road, Bracknell,
registered no: 690597 England Berks RG12 1HN

anon...@gmail.com

unread,
Aug 10, 2007, 9:04:05 AM8/10/07
to
On Aug 10, 2:47 pm, Chris Dollin <chris.dol...@hp.com> wrote:
> When did `({ *(99) = (val); })` become legal syntax? Is this some C99
> thing I missed, or a proprietaryism I've been lucky to escape?

My mistake!
({ *((int *)99) = (val); })
is what was meant.
Thanks!

Chris Dollin

unread,
Aug 10, 2007, 9:09:25 AM8/10/07
to
anon...@gmail.com wrote:

(a) When did `({ *((int *)99) = (val); })` become legal syntax (fx:etc)?

(b) Presumably you know that casting an integer to a pointer and then
assigning through it is horribly unportable, and have Extremely
Good Reasons for juggling swords while dancing on a tightrope
blindfolded while a currently-unemployed nasal demon breaths
gentle flames over the knots.

--
Chris "DON'T PANIC!" Dollin

Hewlett-Packard Limited registered no:
registered office: Cain Road, Bracknell, Berks RG12 1HN 690597 England

Army1987

unread,
Aug 10, 2007, 10:03:54 AM8/10/07
to

#if CONST_INDEX == 0
#define PUT_BYTE(const_index, val) ({ *(77) = (val); })
#elif CONST_INDEX == 1
#define PUT_BYTE(const_index, val) ({ *(99) = (val); })
#endif

This can *not* do what you mean, because CONST_INDEX must be a
preprocessor constant (that's even stricter than a compile-time
constant: for example you can't use sizeof), if it is probably
you don't want to pass two arguments to the macro.
Try
#define PUT_BYTE(const_index, val) ({ *(const_index ? 99 : 77) \
= (val); })
if you know that const_index is either 0 or 1.
Btw the ({ and }) stuff isn't standard C.
--
Army1987 (Replace "NOSPAM" with "email")
No-one ever won a game by resigning. -- S. Tartakower

Army1987

unread,
Aug 10, 2007, 10:05:41 AM8/10/07
to

Putting a block in parentheses only makes sense in some extensions,
not in standard C.

Army1987

unread,
Aug 10, 2007, 10:06:32 AM8/10/07
to

Try with
#define PUT_BYTE0 something
#define PUT_BYTE1 something_else

CBFalconer

unread,
Aug 10, 2007, 10:06:59 AM8/10/07
to

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
# define PUT_BYTE(const_index, val) (something else)
#endif

--
Chuck F (cbfalconer at maineline dot net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net>

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

Ravishankar S

unread,
Aug 10, 2007, 10:55:18 AM8/10/07
to

"Army1987" <army...@NOSPAM.it> wrote in message
news:pan.2007.08.10....@NOSPAM.it...

Ravishankar S

unread,
Aug 10, 2007, 11:28:45 AM8/10/07
to
Assuming val is of type byte only, perhaps you can use inline functions..

static inline void __put_byte(const int index, unsigned char val) {
if(index == 0) {
...

} else if (index == 1) {

}
}

Even if you have val of many types then you use the GNU extension typeof()
( if you use GNU CC that is)

#define PUT_BYTE(const_index,val) {\
if(typeof(val) == typeof(int)) {\
__put_int();\
} else if(typeof(val) == typeof(float) ) {\
__put_float();\
} \

Regards,
Ravi

"CBFalconer" <cbfal...@yahoo.com> wrote in message
news:46BC7103...@yahoo.com...

anon...@gmail.com

unread,
Aug 10, 2007, 11:45:08 AM8/10/07
to
C could have a better way of preprocessing, by allowing computations
on a META-Level, where code is not transformed to machine-code.
However, within this META-Level, one could specify which machine code
is actually desired.

#preprocessor_META_level_ON
...
#machine_code_begin
...
#machine_code_end
...
#preprocessor_META_level_OFF

Below there is an example of this idea!

On Aug 10, 4:06 pm, Army1987 <army1...@NOSPAM.it> wrote:
> On Fri, 10 Aug 2007 05:44:22 -0700, anon.asdf wrote:
> >> #define PUT_BYTE(const_index, val) \
> >> #preprocessor_if (const_index == 0) \
> >> ({ *(77) = (val); }) \
> >> #preprocessor_else_if (const_index == 1) \
> >> ({ *(99) = (val); }) \
> >> #preprocessor_end
>

> > "Can the proprocessor make conditional decisions in macros, based on
> > macro arguments"...
>
> Try with
> #define PUT_BYTE0 something
> #define PUT_BYTE1 something_else


I know of this, but I want to save writing out "millions" of lines, by
getting the preprocessor to figure out the pattern (on a META-Level),
instead of me having to mundanely hardcode a pattern:


/************** 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 *****************/

This would be 4294967296 times better :) - (assuming val is a 4 byte
int)
than the following:

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

//many many lines above!

//In the code I'll have:

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

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


> #define PUT_BYTE(const_index, val) ({ *(const_index ? 99 : 77) \
> = (val); })
>if you know that const_index is either 0 or 1.

Similar to your suggestion above, there'll be people who'll now say:
The compiler will resolve it for you - and that one could go and use
this:


#define GO(val) \
{ if (!(val % 3)) \
*((int *) MEM_MAP_A) = val; \
else \
*((int *) MEM_MAP_B) = val; \
}

But who knows what the compiler will do??? Maby it will NOT resolve it
and actually include the "if" in the machine code. Don't we want
guarantees??

Yes I could also write a program (special_generator.c) to generate a
header file (head.h) with the "millions" of preprocessor-lines I need,
but I'll just argue that it's confusing to have the generator source
(special_generator.c) in a different file, than it's generated result
(head.h)

The beauty of a Meta-Level, would be that the generator information is
not a seperate special C-file, but embedded in itself:
head.h includes a Meta-Level ...

And more importantly, programmers could have guarantees on what is
resolved and what is not resolved.
.
.
.

My main criticism here, is that C does not have a good method of
working on a Meta-Level.

Actually it's not a severe critisism - C is really great!
But it could still evolve, right?!

anon.asdf

anon...@gmail.com

unread,
Aug 10, 2007, 12:13:42 PM8/10/07
to
On Aug 10, 3:09 pm, Chris Dollin <chris.dol...@hp.com> 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); \
})

int main(void)
{
int c;
while (PRE_COND, c != GET_OUT); // 'q' and enter to exit
return 0;
}
/*********end*********

Regards,
Albert

anon...@gmail.com

unread,
Aug 10, 2007, 12:38:19 PM8/10/07
to
Hi all!

I just realized something really strange!

Try this code!

/************* test.c *********************/
#include <stdio.h>

#define GET_OUT 'q'

#define PRE_COND \
({ c = getchar(); \
putchar(c); \
})

int main(void)
{
int c;
while (PRE_COND, c != GET_OUT) {
printf("CHEERS");
}
return 0;
}

/**********************************/

a)
This works OK:

albert@aaa:~/ccc$ ./test
bbbq<Enter>
bCHEERSbCHEERSbCHEERSqalbert@aaa:~/ccc$

b)
albert@aaa:~/ccc$ ./test
b<Enter>
bCHEERS
CHEERSb<Enter>
bCHEERS
CHEERSb<Enter>
bCHEERS
CHEERSq<Enter>
qalbert@aaa:~/ccc$

Why does it print 2 CHEERS in a row??????

This is really confusing me. Is this a compiler error?
(gcc -v smiles at me and says:
gcc version 4.1.2)

Help!

anon...@gmail.com

unread,
Aug 10, 2007, 12:39:48 PM8/10/07
to

Ahhh! Sorry , sorry no compiler error!
Doh! It's the <Enter>.

My huge mistake!
-Albert

CBFalconer

unread,
Aug 10, 2007, 5:01:13 PM8/10/07
to
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)

Dik T. Winter

unread,
Aug 10, 2007, 6:09:21 PM8/10/07
to

gcc -Wall -ansi -pedantic smiles at me and says:

@@P.c: In function `main':
@@P.c:14: warning: ANSI C forbids braced-groups within expressions

--
dik t. winter, cwi, kruislaan 413, 1098 sj amsterdam, nederland, +31205924131
home: bovenover 215, 1025 jn amsterdam, nederland; http://www.cwi.nl/~dik/

pete

unread,
Aug 10, 2007, 7:26:29 PM8/10/07
to
anon...@gmail.com wrote:
>
> Hello!
>
> Can the proprocessor make conditional decisions.

An IOCCC entry in 1995,
solved the Towers of Hanoi, via the C pre-processor,
but I couldn't understand the code.

--
pete

Stephen Sprunk

unread,
Aug 10, 2007, 8:18:55 PM8/10/07
to
<anon...@gmail.com> wrote in message
news:1186749384....@m37g2000prh.googlegroups.com...

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)

(Note that assumes val is of type int; modify the cast if it's some other
type. And, of course, that cast is inherently unportable for at least two
reasons.)

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.

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

Thad Smith

unread,
Aug 10, 2007, 11:47:51 PM8/10/07
to
Richard Tobin wrote:
> In article <1186749384....@m37g2000prh.googlegroups.com>,
> <anon...@gmail.com> 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

Army1987

unread,
Aug 11, 2007, 6:41:48 AM8/11/07
to
On Fri, 10 Aug 2007 19:18:55 -0500, Stephen Sprunk wrote:

> <anon...@gmail.com> wrote in message
> news:1186749384....@m37g2000prh.googlegroups.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

unread,
Aug 11, 2007, 6:47:44 AM8/11/07
to
On Fri, 10 Aug 2007 10:06:59 -0400, CBFalconer wrote:

> anon...@gmail.com 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

unread,
Aug 11, 2007, 6:52:01 AM8/11/07
to
On Fri, 10 Aug 2007 16:13:42 +0000, anon.asdf wrote:

> On Aug 10, 3:09 pm, Chris Dollin <chris.dol...@hp.com> 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))

Marcin Wolcendorf

unread,
Aug 11, 2007, 7:09:10 AM8/11/07
to

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.

Richard

unread,
Aug 11, 2007, 7:40:52 AM8/11/07
to
CBFalconer <cbfal...@yahoo.com> writes:

Back in the killfile you go. And get your signatures sorted out before
you lecture other people on posting styles.

Stephen Sprunk

unread,
Aug 11, 2007, 10:18:27 AM8/11/07
to
"Army1987" <army...@NOSPAM.it> wrote in message
news:pan.2007.08.11....@NOSPAM.it...

> 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.

anon...@gmail.com

unread,
Aug 12, 2007, 8:31:19 AM8/12/07
to wolc...@friko2.onet.pl
On 11 Aug., 13:09, Marcin Wolcendorf <wolce...@friko2.onet.pl> 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, 8);
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:

}

/************** 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.lang.c/msg/4d74e79644f7befd?

-Albert

Army1987

unread,
Aug 12, 2007, 8:39:33 AM8/12/07
to
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.lang.c/msg/4d74e79644f7befd?
>
That's what the compiler is for.

anon...@gmail.com

unread,
Aug 12, 2007, 10:58:33 AM8/12/07
to

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.lang.c/msg/a889a3452cb74c4c?
is interesting though.

?
-Albert

anon...@gmail.com

unread,
Aug 12, 2007, 12:46:19 PM8/12/07
to
On 11 Aug., 02:18, "Stephen Sprunk" <step...@sprunk.org> wrote:

> #define PUT_BYTE(const_index, val) \
> do { \
> if (!const_index) { *(int*)77 = (val); } \
> else { *(int *)99 = (val); } \
>
> } while (0)
>
> (Note that assumes val is of type int; modify the cast if it's some other
> type. And, of course, that cast is inherently unportable for at least two
> reasons.)
>
> 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.
>

But what if I make it a function which evaluates only constants and
returns only constants. In other words the function is only there
during preprocessing and compiler-resolution and -optimization.

Will an inline function guarantee that no superfluous code-bits will
sit in the generated machine code???

Example:

static inline int go(const int index, int val) {
if(index == 0) {
*((int *)77) = val;
} else {
*((int *)77) = val;
}
}

int main(void)
{
go(0, 1);
go(1, 3);

int a;
// calculations with a...
go(a, 8);

}


If all conditionals in the inline are resolved during preprocessing,
compiler-resolution/optimization, then thats nice.

The machine code should only have one conditional for
go(a, 8)
since it is not known before hand, what a will be

Albert

Stephen Sprunk

unread,
Aug 12, 2007, 2:35:21 PM8/12/07
to
<anon...@gmail.com> wrote in message
news:1186937179.7...@w3g2000hsg.googlegroups.com...

> On 11 Aug., 02:18, "Stephen Sprunk" <step...@sprunk.org> wrote:
>> #define PUT_BYTE(const_index, val) \
>> do { \
>> if (!const_index) { *(int*)77 = (val); } \
>> else { *(int *)99 = (val); } \
>>
>> } while (0)
>>
>> (Note that assumes val is of type int; modify the cast if it's some
>> other type. And, of course, that cast is inherently unportable for
>> at least two reasons.)
>>
>> 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.
>
> But what if I make it a function which evaluates only constants and
> returns only constants. In other words the function is only there
> during preprocessing and compiler-resolution and -optimization.
>
> Will an inline function guarantee that no superfluous code-bits will
> sit in the generated machine code???

That's the whole point of inlining. Basically, you get all the performance
and overhead savings of using macros with all the safety and (most of the)
flexibility of functions.

> Example:
>
> static inline int go(const int index, int val) {
> if(index == 0) {
> *((int *)77) = val;
> } else {
> *((int *)77) = val;
> }
> }
>
> int main(void)
> {
> go(0, 1);
> go(1, 3);
>
> int a;
> // calculations with a...
> go(a, 8);
>
> }
>
>
> If all conditionals in the inline are resolved during preprocessing,
> compiler-resolution/optimization, then thats nice.
>
> The machine code should only have one conditional for
> go(a, 8)
> since it is not known before hand, what a will be

Any decent compiler will do that with the appropriate optimizations enabled.
Many will even do it without the function being declared inline, as long as
the function's definition is visible. If your compiler doesn't do this, get
a new one. This has been a standard feature of C compilers ever since C++
made inlining so critical.

Keith Thompson

unread,
Aug 12, 2007, 5:18:09 PM8/12/07
to
"Stephen Sprunk" <ste...@sprunk.org> writes:
[...]

> Any decent compiler will do that with the appropriate optimizations
> enabled. Many will even do it without the function being declared
> inline, as long as the function's definition is visible. If your
> compiler doesn't do this, get a new one. This has been a standard
> feature of C compilers ever since C++ made inlining so critical.

For a loose definition of "standard". As I'm sure you know, the C90
standard doesn't define the 'inline' keyword (though it certainly
permits inlining as an optimization). C99 has the 'inline' keyword,
but it's only a hint, similar to 'register'. A conforming but
low-quality C99 compiler could simply ignore it, or a clever compiler
could ignore it and make its own decisions about which functions to
inline.

If you mean that support for inlining (with or without the keyword) is
a common feature of C compilers because many of them share code with
C++ compilers, you may well be right.

--
Keith Thompson (The_Other_Keith) ks...@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"

柑\/b

unread,
Aug 13, 2007, 2:55:36 AM8/13/07
to
On Sun, 12 Aug 2007 13:35:21 -0500, "Stephen Sprunk" wrote:
>anon wrote in message

i not agree;
if i declare a big function not inline and the compiler inline it =>
the exe size (or the size of some loop) can become too big for the
good use from cpu

Chris Dollin

unread,
Aug 13, 2007, 4:47:41 AM8/13/07
to
anon...@gmail.com wrote:

> On Aug 10, 3:09 pm, Chris Dollin <chris.dol...@hp.com> wrote:
>>
>> (a) When did `({ *((int *)99) = (val); })` become legal syntax (fx:etc)?
>>
>
> Hi Chris!
>
> Here's a nice example that illustrates ({ ... }):

When did `({ ... })` become legal standard C syntax (fx:etc)?

--
Chris "usually it's worked by now" Dollin

Hewlett-Packard Limited registered no:
registered office: Cain Road, Bracknell, Berks RG12 1HN 690597 England

Army1987

unread,
Aug 13, 2007, 5:44:10 AM8/13/07
to
On Mon, 13 Aug 2007 08:55:36 +0200, ¬a\/b wrote:

> On Sun, 12 Aug 2007 13:35:21 -0500, "Stephen Sprunk" wrote:
>>anon wrote in message
>>news:1186937179.7...@w3g2000hsg.googlegroups.com...

>>> static inline int go(const int index, int val) {

[snip]


>>> }
>>>
>>>
>>> If all conditionals in the inline are resolved during preprocessing,
>>> compiler-resolution/optimization, then thats nice.
>>>
>>> The machine code should only have one conditional for
>>> go(a, 8)
>>> since it is not known before hand, what a will be
>>
>>Any decent compiler will do that with the appropriate optimizations enabled.
>>Many will even do it without the function being declared inline,
>
> i not agree;
> if i declare a big function not inline and the compiler inline it =>
> the exe size (or the size of some loop) can become too big for the
> good use from cpu

Any decent compiler will do that only if it understands that it is
worth the trouble. Also, with some compilers you can choose
whether to optimize for space or for time (e.g -Os for gcc).

Army1987

unread,
Aug 13, 2007, 5:49:25 AM8/13/07
to
On Sun, 12 Aug 2007 14:58:33 +0000, anon.asdf wrote:

> On Aug 12, 2:39 pm, Army1987 <army1...@NOSPAM.it> 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.lang.c/msg/4d74e79644f7befd?
>>
>> 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

Add parentheses (1<<8) or there might be great surprises when you
use it in a more complicated expression.

> int a = AAA;
>
> because how do I know what the compiler is going to do, without
> checking the generated asm, or machine code?

1<<8 is a constant integer expression, so it is *very* unlikely to
be actually computed at runtime.

> 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

You have CHAR_BIT defined in <limits.h>.

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

--

pete

unread,
Aug 13, 2007, 6:25:34 AM8/13/07
to
anon...@gmail.com wrote:
>
> On Aug 10, 3:09 pm, Chris Dollin <chris.dol...@hp.com> wrote:
> >
> > (a) When did `({ *((int *)99) = (val); })` become legal syntax (fx:etc)?
> >
>
> Hi Chris!
>
> Here's a nice example that illustrates ({ ... }):
>
> /*********({ ... })**********/

What, the comment?

> #include <stdio.h>
>
> #define GET_OUT 'q'
>
> #define PRE_COND \
> ({ c = getchar(); \
> putchar(c); \
> })

That's no good. That doesn't compile.
Should be:


#define PRE_COND (c = getchar(), putchar(c))

> int main(void)
> {
> int c;
> while (PRE_COND, c != GET_OUT); // 'q' and enter to exit
> return 0;
> }

--
pete

CBFalconer

unread,
Aug 13, 2007, 2:17:00 PM8/13/07
to
Army1987 wrote:
> ÂŹa\/b wrote:
>
... snip ...

>
>> i not agree; if i declare a big function not inline and the
>> compiler inline it the exe size (or the size of some loop) can

>> become too big for the good use from cpu
>
> Any decent compiler will do that only if it understands that it
> is worth the trouble. Also, with some compilers you can choose
> whether to optimize for space or for time (e.g -Os for gcc).

Źa\/b is a known troll. Ignore it.

--
Chuck F (cbfalconer at maineline dot net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net>

Marcin Wolcendorf

unread,
Aug 14, 2007, 4:15:35 PM8/14/07
to
Hi,

anon...@gmail.com wrote:
> On 11 Aug., 13:09, Marcin Wolcendorf <wolce...@friko2.onet.pl> wrote:
> ...
> >

> > 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, 8);
> PUT_BYTE(1, 9);
> return 0;
> }
> /*************/
>
> and it works nicely:
>
> (I don't think we need PUT_BYTE_EXPANDED)

As long, as 0 and 1 are numbers, not defines. If they are '#define'd,
you'll need expansion.

Regards,

M.W.

David Thompson

unread,
Aug 26, 2007, 3:18:09 AM8/26/07
to
On Sat, 11 Aug 2007 09:18:27 -0500, "Stephen Sprunk"
<ste...@sprunk.org> wrote:

> "Army1987" <army...@NOSPAM.it> wrote in message
> news:pan.2007.08.11....@NOSPAM.it...
> > On Fri, 10 Aug 2007 19:18:55 -0500, Stephen Sprunk wrote:
> >> #define PUT_BYTE(const_index, val) \
> >> do { \
> >> if (!const_index) { *(int*)77 = (val); } \
> >> else { *(int *)99 = (val); } \
> >> } while (0)

(versus)


> > #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.
>

Aside: it's officially the 'conditional' operator and commonly called
'ternary', but I've never heard it called 'trinary'.

> > (Note that it always evaluates each argument exactly once.)
>
> It's better in that respect.
>

No, they're the same. The if-else version _evaluates_ only one
occurrence of (val), although it's _written_ twice -- and thus
expanded twice, but expansion by itself isn't a problem, only
execution of those expanded instances.

I personally like the ?: version as it better captures the semantic
similarity, and perhaps even better something like:
* (int*) (int[]){77,99} [idx] = val;
or more legibly
* (int*) addrs [idx] = val
where addrs is arranged to be in scope (most simply global)
as something like static const int addrs [] = {77,99};

But the if-else version is definitely valid -- if storing through
those pointer values is, which applies to all approaches.

- formerly david.thompson1 || achar(64) || worldnet.att.net

0 new messages