Thread: c preprossor

  1. #1
    Registered User
    Join Date
    Jan 2012
    Posts
    5

    c preprossor

    Hi,

    I wonder how could I implement following logic.

    compile will fail. is there a way to work arround?

    #define SIZE(x) \
    #if( x == 16 ) 0x123\
    #elif ( x == 64 ) 0x456\
    #elif ( x == 128 ) 0x789\
    #elif ( x == 512 ) 0xabc\
    #else #error not support size

    basiclly I want SIZE(16) will be substituted by 0x123;
    SIZE(64) be substitued by 0x456; etc ...


    Thx

  2. #2
    Just a pushpin. bernt's Avatar
    Join Date
    May 2009
    Posts
    426
    Is there any reason you can't use
    Code:
    #define SIZE_16 0x123
    #define SIZE_64 0x456
    ...
    ?
    Consider this post signed

  3. #3
    Registered User
    Join Date
    Jan 2012
    Posts
    5
    of cause #define SIZE_16 0x123 works. then if I have many size, then I have to list them all. It's not looks pretty.

  4. #4
    Registered User
    Join Date
    Dec 2011
    Posts
    795
    Quote Originally Posted by lxw View Post
    of cause #define SIZE_16 0x123 works. then if I have many size, then I have to list them all. It's not looks pretty.
    Because we all know that aesthetics > efficiency, simplicity, and good code. /headdesk

    If you have more than you want to list, then do an enum or find a way to programatically use the numbers, but don't try any fancy preprocessor tricks just for the sake of looking good.

    Edit: however, re-reading your first post, it looks like you just want to return a constant number depending on the size of X, and that can be defined as its own function with an inline switch statement.

  5. #5
    Registered User
    Join Date
    Jan 2012
    Posts
    5

    Unhappy

    Quote Originally Posted by memcpy View Post
    Because we all know that aesthetics > efficiency, simplicity, and good code. /headdesk

    however, re-reading your first post, it looks like you just want to return a constant number depending on the size of X, and that can be defined as its own function with an inline switch statement.
    you are right. I want SIZE(x) substituted by constant value, but not return constant value. as I will use this macro in variable define, not in code statement.

  6. #6
    Registered User
    Join Date
    Dec 2011
    Posts
    795
    "Substituted with" is virtually the same as "returned". If you use the macro form:

    Code:
    #define SIZE(x) ( (x == 16) ? 0x123 : \
                             (x == 32) ? 0x321 : \
                             /* etc */
    Then, every instance of SIZE will be replaced with all of the comparison text that's defined. So, if you try to input 32...:

    Code:
    int32_t size = SIZE(16);
    /* translates to: */
    int32_t size = 0x123;

  7. #7
    Registered User
    Join Date
    Jan 2012
    Posts
    5
    thank you memcp, I tried that way. it always substitued by 0 in my compiler. my compiler is /sh4-linux-uclibc-gcc

  8. #8
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    Basically what you want is a really simple template meta-programming program which translates one constant to another constant at compile time.

    I'm feeling generous, so here's exactly what you want:
    Code:
    #include <assert>
    
    #define SIZE(x) (myMetaProg<(x)>::ret)
    template<unsigned x> struct myMetaProg {};
    template<> struct myMetaProg<16> { enum { ret = 0x123 }; };
    template<> struct myMetaProg<64> { enum { ret = 0x456 }; };
    template<> struct myMetaProg<128> { enum { ret = 0x789 }; };
    template<> struct myMetaProg<512> { enum { ret = 0xabc }; };
    
    int main(void)
    {
        assert(SIZE(16) == 0x123);
        char array[128];
        assert(SIZE(sizeof(array)) == 0x789); // could even use a static_assert here
    }
    Warning untested code.

    Also note that this is C++ code; You've posted in the C++ forum afterall. It wont work in C.
    Last edited by iMalc; 01-12-2012 at 11:13 PM.
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  9. #9
    Registered User
    Join Date
    Jan 2012
    Posts
    3
    You can use
    #define SUM(x) ((x) == (16)) ? 0x123: ((x)==64) ? 0x456: ((x)==128) ? 0x789: ((x)==512) ? 0xabc:0x99999999

    Cheers
    Saurabh

  10. #10
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Quote Originally Posted by lxw View Post
    of cause #define SIZE_16 0x123 works. then if I have many size, then I have to list them all. It's not looks pretty.
    It doesn't matter what technique you use. It is necessary to list all the candidate values, regardless.

    Code is not required to look "pretty". It is more important that code be understandable and maintainable.
    Quote Originally Posted by saurabhsharma View Post
    You can use
    #define SUM(x) ((x) == (16)) ? 0x123: ((x)==64) ? 0x456: ((x)==128) ? 0x789: ((x)==512) ? 0xabc:0x99999999
    The weakness of that approach is that it will always compile, even if SIZE(x) is supplied an invalid x. After all, ?: cannot be left incomplete, or it will never compile.

    Apart from iMalc's approach of using template specialisation (which is definitely preferable in C++) there is also a macro technique.
    Code:
    #define SIZE_16 0x123
    #define SIZE_64 0x456
    #define SIZE_128 0x789
    #define SIZE_512 0xabc
    
    #define SIZE(x) SIZE_##x
    This will mean SIZE(x) will work for x = 16,64, 128, 512, but will trigger a compilation error otherwise. If you want it to work for other values of x (not necessarily integral - any token will do) then simply define a corresponding SIZE_x.
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  11. #11
    Registered User
    Join Date
    Jan 2012
    Posts
    5
    thanks you guys all. you must be C expert. I like grumpy's comments.
    It is necessary to list all the candidate values, regardless.

  12. #12
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Say, iMalc, you know you can use static const int variables instead of enums, right? It's preferred nowadays instead of enums.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  13. #13
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    Quote Originally Posted by Elysia View Post
    Say, iMalc, you know you can use static const int variables instead of enums, right? It's preferred nowadays instead of enums.
    I tend to forget which one is preferred there.
    Token pasting operator FTW here I rekon.
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  14. #14
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Code:
    #include <stdio.h>
    
    #define SIZE_16 0x123
    #define SIZE_64 0x456
    #define SIZE_128 0x789
    
    #define SIZE(x) SIZE_##x
    
    int main()
    {
        printf("SIZE(16) = %d\n", SIZE(16));
        printf("SIZE(64) = %d\n", SIZE(64));
        printf("SIZE(128) = %d\n", SIZE(128));
    }
    EDIT: Doh. Once again, I've posted before reading the entire thread first.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

Popular pages Recent additions subscribe to a feed