Thread: Marco translation help

  1. #1
    young grasshopper jwroblewski44's Avatar
    Join Date
    May 2012
    Location
    Where the sidewalk ends
    Posts
    294

    Marco translation help

    Hello everyone. I am working on a non-graded project and am in need of some help. I have this bit of code that I wish to turn into a macro, but I am REALLY lacking in knowledge in that department. Since I'm not really focusing on macros right now, I was wondering if someone could translate my code snippet into a macro for me? It would help me understand the syntax as well. Thanks in advance.

    Code:
    if( *pstack && *pstack->type == OPERAND && 
       *pstack->linked_token && ( *pstack->linked_token )->type == OPERAND )

  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    You want to turn the if statement into a macro, or the conditional expression? Assuming the latter, start with: what are the variables?
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  3. #3
    young grasshopper jwroblewski44's Avatar
    Join Date
    May 2012
    Location
    Where the sidewalk ends
    Posts
    294
    I am really sorry. I forgot to include the definitions and what-not. And yes, to be more specific, I would like the conditional statement to be translated into a macro that would have the same result as the if statement.

    Code:
    /* enable (1) or disable (0) parentheses checking in parsing strings */
    /* leave disabled for part (a); enable for part (b) */
    #define PARSE_PARENS 0
    
    
    /* type of token */
    enum token_type {
        OPERAND, /* number */
        OPERATOR, /* operator: +, -, *, / */
    #if PARSE_PARENS
        LPARENS, /* left parentheses ( */
        RPARENS /* right parentheses ) */
    #endif
    };
    
    
    /* operator identifiers (opcodes) */
    enum op {
        ADD, /* a+b */
        SUBTRACT, /* a-b (binary) */
        MULTIPLY, /* a*b */
        DIVIDE, /* a/b */
        NEGATE /* -a (unary) */
    };
    
    
    /* direction of evaluation (associativity) */
    enum assoc {
        LEFT, /* left-to-right (+, binary -, *, /) */
        RIGHT /* right-to-left (unary -) */
    };
    
    
    /* number of operands for each operator type */
    const unsigned int op_operands[] = {2, 2, 2, 2, 1};
    
    
    /* order-of-operations (precedence) (0 = evaluated last) */
    const unsigned int op_precedences[] = {0, 0, 1, 1, 2};
    
    
    /* evaluation direction (associativity) for each precedence level */
    const enum assoc op_associativity[] = {LEFT, LEFT, RIGHT};
    
    
    /* contains value of token */
    union token_value {
        double operand; /* numeric value for operand */
        enum op op_code; /* opcode for operators */
    };
    
    
    /* data structure for token */
    typedef struct s_expr_token {
        union token_value value; /* numeric value or opcode */
        enum token_type type; /* type of token */
    
    
        struct s_expr_token * linked_token; /* linked token in stack/queue */
    } * p_expr_token; /* p_expr_token is shorthand for "struct s_expr_token *" */
    Those are global to the whole program.

    This is declared within the function I am writing, which is where I would declare the macro. I only need this macro inside this function.
    Code:
    p_expr_token * pstack;*pstack = NULL;   /* holds pointer to top of token stack */
    p_expr_token ptoken;                    /* current token */
    EDIT: I am just lazy as all get-out, and don't want to retype that long if statement when I could shorten it to a small macro.
    Last edited by jwroblewski44; 04-03-2013 at 10:53 PM.

  4. #4
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    It seems to me that you want something like:
    Code:
    #define CHECK_OPERAND_TOKENS(pstack) (*(pstack) && *(pstack)->type == OPERAND && \
                                          *(pstack)->linked_token && (*(pstack)->linked_token)->type == OPERAND)
    To be used as:
    Code:
    if( CHECK_OPERAND_TOKENS(pstack) )
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  5. #5
    young grasshopper jwroblewski44's Avatar
    Join Date
    May 2012
    Location
    Where the sidewalk ends
    Posts
    294
    That is exactly what I am looking for! Thank you very much Laserlight.

    It seems the syntax is to just put parenthesis around the parameter inside the expression? I assume the backslash is necessary to indicate the expression continues on the next line?

  6. #6
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Yeah, I just copied and pasted your code, added the parentheses with the backslash to get a second line for formatting purposes. The parentheses are unnecessary, but better safe than sorry since you might later use a more complicated expression. Same reason for the surrounding parentheses.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  7. #7
    Stoned Witch Barney McGrew's Avatar
    Join Date
    Oct 2012
    Location
    astaylea
    Posts
    420
    The unary * operator is evaluated after the -> operator, so your code applies -> to an incorrect type. My understanding is that you want to ensure that the first member is an operand and the next member is also an operand. In that case you'd be better off writing a function whose name takes a predicate form, for instance:


    Code:
    int double_operand(const struct s_expr_token *token)
    {
        return token && token->type == OPERAND && token->next
            && token->next->type == OPERAND;
    }
    This makes it easy to read when used with an if statement or while statement:

    Code:
    if (double_operand(*pstack)) /* if *pstack is a double operand */
    
    if (!double_operand(*pstack)) /* if *pstack is not a double operand */

  8. #8
    young grasshopper jwroblewski44's Avatar
    Join Date
    May 2012
    Location
    Where the sidewalk ends
    Posts
    294
    The unary * operator is evaluated after the -> operator, so your code applies -> to an incorrect type.

    Very good point. I believe I could remedy the macro by adding some parenthesis?

    Code:
    
    
    Code:
    #define CHECK_OPERAND_TOKENS(pstack) (*(pstack) && (*(pstack))->type == OPERAND && \
                                          (*(pstack))->linked_token && ((*(pstack))->linked_token)->type == OPERAND)
    


    Force the dereference before taking the data memeber?

  9. #9
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    You could, but frankly, just going for a function would be simpler if you don't actually need to ensure that the code is inlined. Furthermore, since this is a helper function, you might just define it as static in the source file without declaring it in the header, and maybe the compiler will inline it anyway.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  10. #10
    young grasshopper jwroblewski44's Avatar
    Join Date
    May 2012
    Location
    Where the sidewalk ends
    Posts
    294
    Thanks for all the advice. I will have to think about how I want to do this. I am pretty sure I want to accomplish this with a macro so I will probably just pass the actual token_pointer that pstack is pointing to in order to avoid the deferencing problems.

  11. #11
    Stoned Witch Barney McGrew's Avatar
    Join Date
    Oct 2012
    Location
    astaylea
    Posts
    420
    Why do you want to use a function-like macro? No type checking is performed on the arguments that are passed to them, rather, they're simply inserted into the replacement expression. At some point you'll probably need to take into consideration that the parameter used by your macro is evaluated four times, so if you happen to pass an expression with side effects they'll be performed each time the expression is evaluated. They're better used for defining syntax rather than functions.

  12. #12
    young grasshopper jwroblewski44's Avatar
    Join Date
    May 2012
    Location
    Where the sidewalk ends
    Posts
    294
    Well the macro is used on the same variable every time it's used, so I have no worries about the type being passed. I do realize that it isn't very portable, as-in useful in other programs.

    I have the same if statement that would have been in my file in multiple places, so this is just a shorthand replacement. Honestly, I really just wanted to learn/use a macro.

    I am curious as to what you mean that macro's are better used for "defining syntax"?

  13. #13
    Stoned Witch Barney McGrew's Avatar
    Join Date
    Oct 2012
    Location
    astaylea
    Posts
    420
    I am curious as to what you mean that macro's are better used for "defining syntax"?
    For instance, if you wanted to define your own syntax for traversing a linked list:

    Code:
    #define for_each_tail(cursor, lst) for(cursor = lst; cursor; cursor = (cursor)->next)
    This could be used like so:

    Code:
    for_each_tail(np, lst) {
            print(np->data);
    }
    EDIT: Some fancier stuff:

    #define for_each(cursor, lst) for (<list type> c_ = lst; c_ && (cursor = c_->data, 1); c_ = c_->next)

    C's macro system isn't really sophisticated enough for doing things like this though.
    Last edited by Barney McGrew; 04-05-2013 at 10:41 PM. Reason: typeof, being a non-standard operator, wasn't really necessary in my previous edit

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. #define Marco I believe
    By Bxsteez in forum C Programming
    Replies: 7
    Last Post: 02-21-2011, 08:13 PM
  2. translation!!
    By impossible in forum C++ Programming
    Replies: 14
    Last Post: 05-31-2008, 05:17 PM
  3. C to C++ translation help?
    By bill.thompson65 in forum C++ Programming
    Replies: 5
    Last Post: 10-21-2007, 12:56 PM
  4. translation
    By VOX in forum A Brief History of Cprogramming.com
    Replies: 4
    Last Post: 07-05-2005, 06:21 PM
  5. marco
    By amit in forum A Brief History of Cprogramming.com
    Replies: 1
    Last Post: 06-29-2002, 09:51 AM