m##__LINE__

Discussion in 'C Programming' started by Francois Grieu, Oct 11, 2005.

  1. 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
    Francois Grieu, Oct 11, 2005
    #1
    1. Advertising

  2. Francois Grieu

    sat Guest

    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


    "Francois Grieu" <> wrote in message
    news:...
    > 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
    sat, Oct 11, 2005
    #2
    1. Advertising

  3. 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
    Serge Paccalin, Oct 11, 2005
    #3
  4. Serge Paccalin <> wrote:

    > 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.
    Francois Grieu, Oct 11, 2005
    #4
  5. Francois Grieu

    Chris Dollin Guest

    Francois Grieu wrote:

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

    --
    Chris "electric hedgehog" Dollin
    Essare - to be. Essen - to be at Messe Essen for SPIEL 05.
    Chris Dollin, Oct 11, 2005
    #5
  6. Chris Dollin <> wrote:

    > 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
    Francois Grieu, Oct 11, 2005
    #6
  7. Chris Dollin <> wrote:

    > 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
    Francois Grieu, Oct 11, 2005
    #7
  8. Francois Grieu

    Kevin Bagust Guest

    Francois Grieu wrote:
    > Serge Paccalin <> wrote:
    >
    >>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 };


    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.
    Kevin Bagust, Oct 11, 2005
    #8
  9. Francois Grieu

    Skarmander Guest

    Kevin Bagust wrote:
    > Francois Grieu wrote:
    >
    >> Serge Paccalin <> wrote:
    >>
    >>> 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 };

    >
    > 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.
    Skarmander, Oct 11, 2005
    #9
  10. Kevin Bagust <> and Skarmander explained:

    > Francois Grieu wrote:
    >> Anyone care to explain why THREE nested macros are necessary ?


    > 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
    Francois Grieu, Oct 11, 2005
    #10
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Imre
    Replies:
    4
    Views:
    622
    Peter Gordon
    Feb 23, 2005
  2. Replies:
    2
    Views:
    478
    Raymond Martineau
    Feb 23, 2005
  3. Spry
    Replies:
    1
    Views:
    925
    Richard Heathfield
    Jul 26, 2003
  4. qazmlp

    Definition of __FILE__, __LINE__

    qazmlp, Aug 9, 2003, in forum: C Programming
    Replies:
    9
    Views:
    601
    Mark McIntyre
    Aug 19, 2003
  5. Paul Shipley

    Using __LINE__ as a string

    Paul Shipley, Oct 21, 2003, in forum: C Programming
    Replies:
    18
    Views:
    759
    Dan Pop
    Oct 23, 2003
Loading...

Share This Page