pass block instruction as macro's argument in C

后端 未结 3 812
鱼传尺愫
鱼传尺愫 2021-01-26 18:02

I don\'t know if that is possible, I want to pass a block of instructions in macro like an argument.I will show you an example:

#define ADD_MACRO(size, BLOCK){ f         


        
相关标签:
3条回答
  • 2021-01-26 18:36

    The only problem with the given macro is that it doesn't handle commas in the BLOCK. Commas are tolerated by a variadic macro parameter:

    #define ADD_MACRO(size, ...) do { for(int i=0; i<size; i++){\
                                          __VA_ARGS__} } while(0)
    

    (Also, common practice is to enclose statement macros in do … while(0) to force the user to include a semicolon.)

    (Of course, the original problem may have a better solution. The preprocessor is a blunt instrument. This is the preprocessor solution to the stated question.)

    0 讨论(0)
  • 2021-01-26 18:36

    You can do this by simply showing a block into the macro, or by using a variadic macro as suggested in another answer. However, I wouldn't recommend using macros for this purpose, as it tends to make the code less readable, more error-prone and harder to read/maintain.

    Instead, for generic programming, consider using function pointers corresponding to the desired functionality.

    Another option is to use the C11 _Generic macro to create type safe, generic code. Example:

    #include <stdio.h>
    #include <ctype.h>
    
    void int_increase (int* item)
    {
      (*item)++;
    }
    
    void char_increase (char* item)
    {
      (*item)++;
    }
    
    void int_print (int* item)
    {
      printf("%d ", *item);
    }
    
    void char_print (char* item)
    {
      printf("%c", *item);
    }
    
    void int_clear (int* item)
    {
      *item = 0;
    }
    
    void char_clear (char* item)
    {
      *item = '\0';
    }
    
    void int_traverse (int* data, size_t size, void(*action)(int*))
    {
      for(size_t i=0; i<size; i++)
      {
        action(&data[i]);
      }
    }
    
    void char_traverse (char* data, size_t size, void(*action)(char*))
    {
      for(size_t i=0; i<size; i++)
      {
        action(&data[i]);
      }
    }
    
    #define do_something(data, size, action)  \
      _Generic((data), int*  : int_traverse,  \
                       char* : char_traverse) \
      ( (data), (size), _Generic((data), int*: int_ ## action , char*: char_ ## action ) )
    
    int main (void)
    {
      int int_data [] = {1, 2, 3, 4, 5};
    
      do_something(int_data, 5, increase);
      do_something(int_data, 5, print); 
      printf("\n");
      do_something(int_data, 5, clear);
      do_something(int_data, 5, print); 
      printf("\n");
    
      char char_data [] = "ABCDE";
      do_something(char_data, 5, increase);
      do_something(char_data, 5, print); 
      printf("\n");
      do_something(char_data, 5, clear);
      do_something(char_data, 5, print); 
      printf("\n");
      return 0;
    }
    

    Output:

    2 3 4 5 6
    0 0 0 0 0
    BCDEF
    

    Simply add more of the similar kind of functions if you need to use other types.

    0 讨论(0)
  • 2021-01-26 18:38

    thks for all, especially Potatosmatters, so I follow your directives and I would like to resume your answer into small code that can be useful for the others:

    #define CALL_MACRO(size,instructions){ for(int i=0;i<size; i++){\ 
                                               instructions ;} }
    ......
     //put whatever you want into 'instructions'
     CALL_MACRO(100,for(int y=0; y<3; y++){ (inst1);
                                            (inst2);..} );
     CALL_MACRO(100,(other inst1);(other inst2);.. );
    

    So the result of CALL_MACRO depends on what you insert as instructions.

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