Я объявил функцию со следующей сигнатурой (реализация упрощена):
#include <stdio.h>
struct test_s{
int a, b;
};
void foo(struct test_s **out, size_t *szs, size_t arr_len){
for(size_t i = 0; i < arr_len; i++){
for(size_t j = 0; j < szs[i]; j++){
struct test_s ts = out[i][j];
printf("a = %d; b = %d\n", ts.a, ts.b);
}
}
}
Если вызывающая сторона использует массивы для настройки на указатели, ее можно вызвать следующим образом:
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);
}
Как видно, вызов функции выглядит сложным, подверженным ошибкам и трудным для чтения.
Когда дело доходит до использования трех аргументов, ситуация ухудшается:
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);
}
Так чтоидеально подходит для реализации в качестве макроса, когда дело доходит до массивов. Это довольно просто реализовать следующим образом:
#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)
Я вижу 2 проблемы с таким макросом:
- Мне нужно определить
FOO_ARR_3
, FOO_ARR_4
,и т.д ... - Отсутствие безопасности типа. Если вызывающий абонент передает что-то другое, то
struct test_s[]
ВОПРОС: Можно ли реализовать его как макропеременную макро-функцию, такую как #define FOO_ARR(...)