Can a C macro contain temporary variables?

后端 未结 9 638
忘掉有多难
忘掉有多难 2020-12-16 15:25

I have a function that I need to macro\'ize. The function contains temp variables and I can\'t remember if there are any rules about use of temporary variables in macro subs

相关标签:
9条回答
  • 2020-12-16 15:56

    Yes it should work as you use a block structure and the temp variables are declared in the inner scope of this block.

    Note the last \ after the } is redundant.

    0 讨论(0)
  • 2020-12-16 15:58

    A not perfect solution: (does not work with recursive macros, for example multiple loops inside each other)

    #define JOIN_(X,Y) X##Y
    #define JOIN(X,Y) JOIN_(X,Y)
    #define TMP JOIN(tmp,__LINE__)
    
    #define switch(x,y) int TMP = x; x=y;y=TMP
    
    int main(){
      int x = 5,y=6;
      switch(x,y);
      switch(x,y);
    }
    

    will become after running the preprocessor:

    int main(){
       int x=5,y=6;
       int tmp9 = x; x=y; y=tmp9;
       int tmp10 = x; x=y; y=tmp10;
    }
    
    0 讨论(0)
  • 2020-12-16 16:03

    There are only two conditions under which it works in any "reasonable" way.

    1. The macro doesn't have a return statement. You can use the do while trick.

      #define macro(x) do { int y = x; func(&y); } while (0)
      
    2. You only target GCC.

      #define min(x,y) ({ int _x = (x), _y = (y); _x < _y ? _x : _y; })
      

    It would help if you explain why you have to use a macro (does your office have "macro mondays" or something?). Otherwise we can't really help.

    0 讨论(0)
  • 2020-12-16 16:03

    C macros are only (relatively simple) textual substitutions.

    So the question you are maybe asking is: can I create blocks (also called compound statements) in a function like in the example below?

    void foo(void)
    {
        int a = 42;
        {   
            int b = 42;
            {
                int c = 42; 
            } 
        }
    }
    

    and the answer is yes.

    Now as @DietrichEpp mentioned it in his answer, if the macro is a compound statement like in your example, it is a good practice to enclose the macro statements with do { ... } while (0) rather than just { ... }. The link below explains what situation the do { ... } while (0) in a macro tries to prevent:

    http://gcc.gnu.org/onlinedocs/cpp/Swallowing-the-Semicolon.html

    Also when you write a function-like macro always ask yourself if you have a real advantage of doing so because most often writing a function instead is better.

    0 讨论(0)
  • 2020-12-16 16:08

    Eldar's answer shows you most of the pitfalls of macro programming and some useful (but non standard) gcc extension.

    If you want to stick to the standard, a combination of macros (for genericity) and inline functions (for the local variables) can be useful.

    inline
    long fooAlloc(void *f, size_t size)
    {
       size_t      i1, i2;
       double   *data[7];
    
       /* do something */
       return 42;
    }
    
    
    #define ALLOC_FOO(T) fooAlloc(malloc(sizeof(T)), sizeof(T))
    

    In such a case using sizeof only evaluates the expression for the type at compile time and not for its value, so this wouldn't evaluate F twice.

    BTW, "sizes" should usually be typed with size_t and not with long or similar.

    Edit: As to Jonathan's question about inline functions, I've written up something about the inline model of C99, here.

    0 讨论(0)
  • 2020-12-16 16:12

    They can. They often shouldn't.

    Why does this function need to be a macro? Could you inline it instead?

    0 讨论(0)
提交回复
热议问题