传递块指令作为C中的宏参数

时间:2017-03-14 15:49:55

标签: c macros

我不知道是否可能,我想在宏中传递一个指令块,就像一个参数。我会给你一个例子:

#define ADD_MACRO(size, BLOCK){ for(int i=0; i<size; i++){\
                                    BLOCK} }
你怎么看待它?

感谢您的帮助

3 个答案:

答案 0 :(得分:2)

给定宏的唯一问题是它不会处理BLOCK中的逗号。变量宏参数可以容忍逗号:

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

(另外,通常的做法是在do … while(0)中包含语句宏以强制用户包含分号。)

(当然,原始问题可能有更好的解决方案。预处理器是一种钝器。这是所述问题的预处理器解决方案。)

答案 1 :(得分:1)

您可以通过在宏中显示一个块,或者使用另一个答案中建议的可变参数宏来完成此操作。但是,我不建议为此目的使用宏,因为它往往会使代码更不易读,更容易出错,更难以阅读/维护。

相反,对于泛型编程,请考虑使用与所需功能相对应的函数指针。

另一种选择是使用C11 _Generic宏来创建类型安全的通用代码。例如:

#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;
}

输出:

2 3 4 5 6
0 0 0 0 0
BCDEF

如果您需要使用其他类型,只需添加更多相似类型的功能。

答案 2 :(得分:0)

总而言之,尤其是Potatosmatters,所以我遵循你的指令,我想将你的答案恢复为对其他人有用的小代码:

#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);.. );

因此CALL_MACRO的结果取决于您作为说明插入的内容。