Comm in macros

Discussion in 'C Programming' started by valtih1978, Feb 13, 2014.

  1. valtih1978

    valtih1978 Guest

    I convert ADD_ADDR(@addr, 192,168,3, 1) into

    #define IP_NET 192,168,3
    ADD_ADDR(@addr, IP_NET, 1)

    and get 'ADD_ADDR is undefined'
     
    valtih1978, Feb 13, 2014
    #1
    1. Advertisements

  2. valtih1978

    Eric Sosman Guest

    Please post a complete example, including the definition
    of ADD_ADDR. From what you've shown, we can only guess at what
    you mean by "convert."
     
    Eric Sosman, Feb 13, 2014
    #2
    1. Advertisements

  3. ADD_ADDR is is, presumably, a 5-argument function-like macro. The
    invocation that you show has only three arguments and the C
    pre-processor won't like that. The error message is a little less than
    helpful, because it could have said something more like gcc says:

    error: macro "ADD_ADDR" requires 5 arguments, but only 3 given

    The problem is that the C pre-processor does not work as you expect.
    Macros are not expanded as the arguments are being collected, so IP_NET
    stays as one token.

    It's not clear what the best fix is. Some idea of what the macros are
    meant to achieve would help, but one obvious fix is to provide a
    3-argument version of the macro:

    #define ADD_ADDR3(addr, net, d) ADD_ADDR(addr, net, d)

    It works because macros are expanded when a macro invocation is replaced
    by its body.

    (By the way, the '@' looks very odd.)
     
    Ben Bacarisse, Feb 13, 2014
    #3
  4. valtih1978

    Phil Carmody Guest

    I'm happy for you.
    I'm sad for you.

    Now would you like to ask a sensible question which doesn't
    require us to be inside your head to understand?
    http://www.catb.org/~esr/faqs/smart-questions.html#bespecific
    http://www.catb.org/~esr/faqs/smart-questions.html#beprecise

    Due to the precedence of ',', note that
    #define IP_NET 192,168,3
    is asking for an enormous number of nasty unwanted things to
    happen. Avoid making the right hand side of a macro definition
    anything which could be split into multiple parts or in different
    ways depending on context.

    Phil
    --
    What Alice Hill, President at Slashdot Media, writes:
    Proven track record innovating and improving iconic websites
    (Slashdot.org, ...) while protecting their voice and brand integrity
    What Alice Hill means:
    2013: Completely fucked up Slashdot, and ignored almost endless
    negative feedback about her unwanted changes. 2014: Killed slashdot.
     
    Phil Carmody, Feb 13, 2014
    #4
  5. valtih1978

    Kaz Kylheku Guest

    Are you sure? Perhaps your compiler says that ADD_ADDR cannot be
    called with three arguments?

    IP_NET is a single macro argument. It is identified as the second
    argument of the macro call, and only then does expansion take
    which produces the commas.

    To fix this you have to make a three-argument ADD_ADDR.

    Consider this example:

    #define abc(A, B, C) f(A, B, C)
    #define xy(X, Y) abc(X, Y)
    #define two3 2, 3
    xy(1, two3)

    Expansion with gcc's preprocessor, from the shell:

    $ gcc -E macro.c
    # 1 "macro.c"
    # 1 "<built-in>"
    # 1 "<command-line>"
    # 1 "macro.c"



    f(1, 2, 3)


    (That doesn't prove it's standard or correct, of course; it's just
    a confidence-improving test case.)

    As you can see, the xy(X, Y) macro serves as a two-argument interface
    to the abc macro. Y is expected to be some item that expands to
    a two-element comma separated list.
     
    Kaz Kylheku, Feb 13, 2014
    #5
  6. valtih1978

    Jorgen Grahn Guest

    I don't see why you have to do it this way (although you don't explain
    what you're trying to do).

    With IP/IPv6 addresses, I find (for my use cases) that it's better to:

    - keep them as strings for as long as possible, if that's
    what they start out as
    - use getaddrinfo()[1] if you need to use them to create sockets
    etc; that one too takes strings
    - when that's no longer feasible, switch over to struct in_addr or
    struct in6_addr using inet_ntop/inet_pton.

    I also get the impression you are about 20 years behind. We have
    classless routing now, and A, B and C networks have gone the way of
    the dodo. 192.168.3.x is now[2] 192.168.0/24, and you also have to
    consider 192.168.0/25, 192.168.0/26, 192.168.128/25 in the general
    case ...

    /Jorgen

    [1] Or whatever your environment supplies. I'm assuming POSIX, but
    surely Windows has something equivalent.
     
    Jorgen Grahn, Feb 15, 2014
    #6
    1. Advertisements

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 (here). After that, you can post your question and our members will help you out.