Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/69.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 宏函数,以避免函数调用期间样板文件的大小_C_Function_Macros_Type Safety_Variadic - Fatal编程技术网

C 宏函数,以避免函数调用期间样板文件的大小

C 宏函数,以避免函数调用期间样板文件的大小,c,function,macros,type-safety,variadic,C,Function,Macros,Type Safety,Variadic,我声明了一个具有以下签名的函数(简化了实现): 可以看出,函数调用看起来复杂、容易出错且难以读取 当涉及到使用3个参数时,情况会变得更糟: int main(void){ struct test_s a1[] = {{0, 1}, {2, 3}, {4, 5}}; struct test_s a2[] = {{4, 6}}; struct test_s a3[] = {{2, 3}, {4, 5}}; foo((struct test_s *[]){a1, a2,

我声明了一个具有以下签名的函数(简化了实现):

可以看出,函数调用看起来复杂、容易出错且难以读取

当涉及到使用3个参数时,情况会变得更糟:

int main(void){
    struct test_s a1[] = {{0, 1}, {2, 3}, {4, 5}};
    struct test_s a2[] = {{4, 6}};
    struct test_s a3[] = {{2, 3}, {4, 5}};
    foo((struct test_s *[]){a1, a2, a3},
        (size_t[]){sizeof a1 / sizeof(struct test_s), sizeof a2 / sizeof(struct test_s), sizeof a3 / sizeof(struct test_s)},
        3);
}
因此,当涉及到数组时,最好将其实现为宏。实现它非常简单,如下所示:

int main(void){
    struct test_s a1[] = {{0, 1}, {2, 3}, {4, 5}};
    struct test_s a2[] = {{4, 6}};
    foo((struct test_s *[]){a1, a2}, 
        (size_t[]){sizeof a1 / sizeof(struct test_s), sizeof a2 / sizeof(struct test_s)}, 
        2);
}
#define FOO_ARR_2(a1, a2) \
    do{ \
        foo((struct test_s *[]){a1, a2},  \
        (size_t[]){sizeof a1 / sizeof(struct test_s), sizeof a2 / sizeof(struct test_s)}, \
        2);\
    } while(0)
我发现这样一个宏有两个问题:

  • 我必须定义
    FOO_ARR_3
    FOO_ARR_4
    ,等等
  • 缺乏类型安全性。如果调用方通过了不同的测试,则
    struct test\u s[]

  • 问题:是否有可能将其实现为一个变量宏函数,如
    #define FOO_ARR(…)

    与其将复杂的初始化封装成一个复杂的(如果可能的话)变量宏,不如将该函数本身声明为变量宏

    这可能是这样的:

    #include <stdio.h>
    #include <stdarg.h>
    
    /* expects: number-of-arrays followed by 
       number-of-arrays tuples {arrays-size,  pointer to array's 1st element} */
    
    struct test_s{
      int a, b;
    };
    
    void foo(size_t arr_len, ...)
    {
      va_list vl;
    
      va_start(vl, arr_len);
    
      for (size_t i = 0; i < arr_len; ++i) 
      {
        size_t s = va_arg(vl, size_t);
        struct test_s * p = va_arg(vl, struct test_s *);
    
        for (size_t j = 0; j < s; ++j)
        {
          struct test_s ts = p[j];
          printf("a = %d; b = %d\n", ts.a, ts.b);
        }
      }
    
      va_end(vl);
    }
    
    struct test_s{
      int a, b;
    };
    
    void foo(size_t, ...);
    
    int main(void)
    {
      /* using two arrays: */
      {
        struct test_s a1[] = {{0, 1}, {2, 3}, {4, 5}};
        struct test_s a2[] = {{4, 6}};
    
        foo(2, 
          sizeof a1 / sizeof *a1, a1, 
          sizeof a2 / sizeof *a2, a2
        );
      }
    
      /* using three arrays: */
      {
        struct test_s a1[] = {{0, 1}, {2, 3}, {4, 5}};
        struct test_s a2[] = {{4, 6}};
        struct test_s a3[] = {{2, 3}, {4, 5}};
    
        foo(3, 
          sizeof a1 / sizeof *a1, a1, 
          sizeof a2 / sizeof *a2, a2,
          sizeof a3 / sizeof *a3, a3
        );
      }
    }
    

    “我声明了一个具有以下签名的函数”您是使用此签名绑定到此函数,还是可以随意更改它?@alk是的,如果签名可以简化函数,则可以更改签名call@alk但是我还需要支持
    malloc
    ed指针。这就是它被宣布为那样的原因
    struct test_s{
      int a, b;
    };
    
    void foo(size_t, ...);
    
    int main(void)
    {
      /* using two arrays: */
      {
        struct test_s a1[] = {{0, 1}, {2, 3}, {4, 5}};
        struct test_s a2[] = {{4, 6}};
    
        foo(2, 
          sizeof a1 / sizeof *a1, a1, 
          sizeof a2 / sizeof *a2, a2
        );
      }
    
      /* using three arrays: */
      {
        struct test_s a1[] = {{0, 1}, {2, 3}, {4, 5}};
        struct test_s a2[] = {{4, 6}};
        struct test_s a3[] = {{2, 3}, {4, 5}};
    
        foo(3, 
          sizeof a1 / sizeof *a1, a1, 
          sizeof a2 / sizeof *a2, a2,
          sizeof a3 / sizeof *a3, a3
        );
      }
    }