0

I've found a interesting code snippet that works pretty strange

#include <iostream>
#include <cstdio>
#define DEBUG_CMD(cmd)                                                                             \
    do {                                                                                           \
        cmd;                                                                                       \
    } while (false)

using namespace std;

int main()
{
    cout<<"Hello World";
    DEBUG_CMD({
        int x = 1;
        int y = 1;
        //int x= 1, y =1; // enable this and comment two lines above will yield an error
        printf("x: %d y: %d\n", x, y);
    });

    return 0;
}

when I define x, y seperately, the code can run. but when I define x y in the same statement sperated by comma, the compiler complains about the syntax error.

main.cpp:26:6: error: macro "DEBUG_CMD" passed 2 arguments, but takes just 1
     });
      ^
main.cpp: In function ‘int main()’:
main.cpp:21:5: error: ‘DEBUG_CMD’ was not declared in this scope
     DEBUG_CMD({
     ^~~~~~~~~

I wonder what's happening here.

TIPS: you can compile it at https://onlinegdb.com/ryUuyZEmO and it also gives you the same error.

John Kugelman
  • 349,597
  • 67
  • 533
  • 578
Liu Weibo
  • 434
  • 5
  • 16
  • It's not that it isn't allowed. The problem is that a comma is used to separate macro arguments, so that use of `DEBUG_CMD` has two arguments, not 1. Sometimes you can get around that by putting the argument inside parentheses, so that the comma is not at the top level. That won't work here. – Pete Becker Mar 08 '21 at 19:54
  • Is there any work-around here? – Liu Weibo Mar 08 '21 at 19:58
  • There is https://stackoverflow.com/a/19841470/6752050 – 273K Mar 08 '21 at 20:01
  • What is the purpose of the macro? Trying to pass an entire block of code as an argument is fraught with peril. And anyways, using macros is typically discouraged in C++. If you tell us what you're trying to do perhaps we can suggest a non-macro alternative. – John Kugelman Mar 08 '21 at 20:02
  • 1
    In this question, if arguments are not required to be accessed by names, the solution would be `#define DEBUG_CMD(...) \
    do { \
    __VA_ARGS__; \
    } while (false)` https://ideone.com/d0Xp9V
    – 273K Mar 08 '21 at 20:08
  • @S.M. It works! thank you! – Liu Weibo Mar 08 '21 at 21:38
  • @JohnKugelman Oh, this simply for debugging purpose. This gives me code with indentation as normal code. So I choose it over #ifdef method. – Liu Weibo Mar 08 '21 at 21:40
  • Reduce your pain and headaches. Use functions instead of macros. Let the compiler worry about the optimizations. – Thomas Matthews Mar 08 '21 at 21:58

0 Answers0