m##__LINE__

F

Francois Grieu

Hello,

I wrote this:

#define M(x) enum { m##__LINE__ = x };
#line 1000
M(126)
M(341)
M(565)
...

expecting the preprocessor to build

enum { m1000 = 126 };
enum { m1001 = 341 };
enum { m1002 = 565 };
...

but instead got

enum { m__LINE__ = 126};
enum { m__LINE__ = 341};
enum { m__LINE__ = 565};
...

which of course did not copile.

Is there any solution to produce the expected result,
without entering the a sequence like 1000 1001 1002.. ?

I tried

#define M(l,x) enum { m##l = x };
#line 1000
M(__LINE__,126)
M(__LINE__,341)
M(__LINE__,565)
...

and similarly failed.

Note: I do not want to put these values into an array; I want
them as enum, which allows me to sort them using the compiler
with a sorting network, rather than at runtime.


TIA,

François Grieu
 
S

sat

Hi Francois
lets assume that we do end up creating preprocessed enums like what you
have mentioned here. But, what are you trying to achieve by such a thing.
You would end up with
enum { m1000 = 126 };
enum { m1001 = 341 };
enum { m1002 = 565 };

which are generated before compile time, but how are you going to access
them in the code.. How do you know if 126 was the first (1000) enum and 341
was the second ( 1001) enum..
May be if you give the use case it would be easier to look at it and
appreciate the whole effort ..


sat
 
S

Serge Paccalin

Le mardi 11 octobre 2005 à 10:28:05, Francois Grieu a écrit dans
comp.lang.c :
I wrote this:

#define M(x) enum { m##__LINE__ = x };
#line 1000
M(126)
M(341)
M(565)
..

expecting the preprocessor to build

enum { m1000 = 126 };
enum { m1001 = 341 };
enum { m1002 = 565 };
..

but instead got

enum { m__LINE__ = 126};
enum { m__LINE__ = 341};
enum { m__LINE__ = 565};

You need more macros to make sure __LINE__ is evaluated before being
glued to "m":

#define M__(l) m##l
#define M_(l) M__(l)
#define M(x) enum { M_(__LINE__) = x };

--
___________ 11/10/2005 13:10:12
_/ _ \_`_`_`_) Serge PACCALIN -- sp ad mailclub.net
\ \_L_) Il faut donc que les hommes commencent
-'(__) par n'être pas fanatiques pour mériter
_/___(_) la tolérance. -- Voltaire, 1763
 
F

Francois Grieu

Serge Paccalin said:
You need more macros to make sure __LINE__ is evaluated before
being glued to "m"

Many thanks, it works!
Anyone care to explain why THREE nested macros are necessary ?

#define M__(l) m##l
#define M_(l) M__(l)
#define M(x) enum { M_(__LINE__) = x };

#line 1000
M(565)
M(126)
M(341)
M(747)
enum {MustHave4Lines = 0/(__LINE__-1000==4)};

#define C(a,b) M_(a)>M_(b) // or another order
// for sorting networks, see TAOCP Vol 3
#define S(a,b,c,d) enum{M_(c)=C(a,b)?M_(a):M_(b),\
M_(d)=C(a,b)?M_(b):M_(a)};
S(1000,1002,2000,2002);S(1001,1003,2001,2003);
S(2000,2001,4000,3001);S(2002,2003,3002,4003);
S(3001,3002,4001,4002);
const int t[] = {M_(4000),M_(4001),M_(4002),M_(4003)};

#include<stdio.h>
int main(void)
{int j;
for(j=sizeof t/sizeof*t;j;)printf("%d\n",t[--j]);
return 0;}



François Grieu

PS: This is not an entry to the obfuscated C contest; I need
a table of constants sorted according to a such a complex
criteria that it is unpractical to sort it by hand, an I am
dealing with the limitations of an embedded platform, where
sorting in RAM is not an option.
 
C

Chris Dollin

Francois said:
PS: This is not an entry to the obfuscated C contest; I need
a table of constants sorted according to a such a complex
criteria that it is unpractical to sort it by hand, an I am
dealing with the limitations of an embedded platform, where
sorting in RAM is not an option.

Sort it by machine and generate C code.
 
F

Francois Grieu

Chris Dollin said:
Sort it by machine and generate C code.

[OT] Yes, I did this previously, but I can't figure out
how to invoke an external tool and craft make rules within
the IDE (MW CW 4.2...) hosting the only known C compiler
for my target. And the table to sort changes several
times a day, during development, and I fear we forget to
invoke the sort tool.

So I decided to make a tool generating (once only)
C source code for a sorting network so that the C
compiler will do the job without an external tool.
Thanks to your trick, it is gona work ! And it's fun.


Francois Grieu
 
F

Francois Grieu

Chris Dollin said:
Sort it by machine and generate C code.

[OT] Yes, I did this previously, but I can't figure out
how to invoke an external tool and craft make rules within
the IDE (MW CW 4.2...) hosting the only known C compiler
for my target. And the table to sort changes several
times a day, during development, and I fear we forget to
invoke the sort tool.
So I decided to make a tool generating (once only)
C source code for a sorting network so that the C
compiler will do the job without an external tool.
Thanks to Serge's trick, it is gona work ! And it's fun.


Francois Grieu
 
K

Kevin Bagust

Francois said:
Many thanks, it works!
Anyone care to explain why THREE nested macros are necessary ?

#define M__(l) m##l
#define M_(l) M__(l)
#define M(x) enum { M_(__LINE__) = x };

IIRC With the following macros:

#define M_(l) m##l
#define M(x) enum { M_(__LINE__) = x };

the preprocessor will do the following sequence of replacements:
1) M(565)
2) enum { M_(__LINE__) = 565 }; /* Replace macro M and arguments */
3) enum { m##__LINE__ = 565 }; /* Replace macro M_ as next on line */
4) enum { m__LINE__ = 565 }; /* Process ## highest precedence */

Where as with the three macro version it will do the following:
1) M(565)
2) enum { M_(__LINE__) = 565 }; /* Replace macro M and arguments */
3) enum { M__(__LINE__) = 565 }; /* Replace macro M_ as next on line */
4) enum { M__(1001) = 565 }; /* Replace __LINE__ with the current
line number */
3) enum { m##1001 = 565 }; /* Replace macro M__ */
4) enum { m__LINE__ = 565 }; /* Process ## highest precedence */

So basically as soon as a preprocessor see a # or a ## in the current
stream of tokens to be preprocessed the very next thing that it will do
is to either convert the argument to a string or concatenate the two
arguments.

Kevin.
 
S

Skarmander

Kevin said:
IIRC With the following macros:

#define M_(l) m##l
#define M(x) enum { M_(__LINE__) = x };

the preprocessor will do the following sequence of replacements:
1) M(565)
2) enum { M_(__LINE__) = 565 }; /* Replace macro M and arguments */
3) enum { m##__LINE__ = 565 }; /* Replace macro M_ as next on line */
4) enum { m__LINE__ = 565 }; /* Process ## highest precedence */

Where as with the three macro version it will do the following:
1) M(565)
2) enum { M_(__LINE__) = 565 }; /* Replace macro M and arguments */
3) enum { M__(__LINE__) = 565 }; /* Replace macro M_ as next on line */
4) enum { M__(1001) = 565 }; /* Replace __LINE__ with the current
line number */
3) enum { m##1001 = 565 }; /* Replace macro M__ */
4) enum { m__LINE__ = 565 }; /* Process ## highest precedence */
Unfortunate copy/pasting here; last two lines should be

5) enum { m##1001 = 565 }; /* Replace macro M__ */
6) enum { m1001 = 565 }; /* Process ## */

S.
 
F

Francois Grieu

When expanding
#define M_(l) m##l
#define M(x) enum { M_(__LINE__) = x };

the preprocessor will do the following sequence of replacements:
1) M(565)
2) enum { M_(__LINE__) = 565 }; /* Replace macro M and arguments */
3) enum { m##__LINE__ = 565 }; /* Replace macro M_ as next on line */
4) enum { m__LINE__ = 565 }; /* Process ## highest precedence */
but
#define M__(l) m##l
#define M_(l) M__(l)
#define M(x) enum { M_(__LINE__) = x };

this three macro version it will do the following:
1) M(565)
2) enum { M_(__LINE__) = 565 }; /* Replace macro M and arguments */
3) enum { M__(__LINE__) = 565 }; /* Replace macro M_ as next on line */
4) enum { M__(1001) = 565 }; /* Replace __LINE__ with current line nb */
5) enum { m##1001 = 565 }; /* Replace macro M__ */
6) enum { m1001 = 565 }; /* Process ## */

I now see the light. The M_ to M__ replacement delays reaching ## until
__LINE__ has been expanded. Clever. Is this par ANSI/ISO C89/90 ?


François Grieu
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top