Передача массива int переменной длины в качестве параметра функции в Objective C
-
05-07-2019 - |
Вопрос
У меня есть следующий код, который работает нормально...
int testarr[3][3] = {
{1,1,1},
{1,0,1},
{1,1,1}
};
[self testCall: testarr];
Который вызывает эту функцию:
- (void)testCall: (int[3][3]) arr {
NSLog(@"cell value is %u",arr[1][1]);
}
Мне нужно, чтобы массив имел переменную длину. Как лучше всего объявить функцию?
Использование пробелов не работает:
- (void)testCall: (int[][]) arr {
Спасибо за вашу помощь.
Решение
Я бы написал это так:
- (void) testCall: (int *) aMatrice;
Это позволяет вам избежать нескольких malloc, и математика для вычисления одного смещения в линейном массиве на основе координат x, y в 2D-массиве является тривиальной. Это также позволяет избежать множественных mallocs, подразумеваемых int **, и ограничений синтаксиса 2D-массивов, сохраняемых языком.
Итак, если вам нужен массив 4x5, вы можете сделать следующее:
#define WIDTH 4
#define HEIGHT 5
#define INDEXOF(x,y) ((y*WIDTH) + x)
int *myArray = malloc(sizeof(int) * 5 * ELEMS_PER_ROW);
Затем можно инициализировать массив линейно или с помощью вложенного цикла for:
for(int x=0; x<width; x++)
for(int y=0; y<height; y++)
myArray[INDEXOF(x,y)] = ... some value ...;
И вы передадите его методу:
[foo testCall: myArray];
Хотя вы, возможно, захотите также нести ширину и высоту или, что еще лучше, создать подкласс IntMatrix NSObject, который обернет всю арифметику и хранилище указателей за пределы красивого чистого API.
(весь код введен в SO)
Другие советы
Массивы C не могут быть переменными в нескольких измерениях.
Этого не может быть:
int testarr[][] = {
{1,1,1},
{1,0,1,2},
{1,1}
};
Но вы можете иметь это:
int testarr[][3] = {
{1,1,1},
{1,0,1},
{1,1,1},
{4,5,6},
{7,8,9}
}
foo(testarr);
void foo(int param[][3])
{
printf("%d", param[3][1]); // prints 5
}
Вы не можете использовать int [] []
, потому что размер второго измерения влияет на расположение массива в памяти. Если вы знаете второе измерение, вы можете использовать int [] [x]
, в противном случае вам придется использовать int **
, к которому можно обращаться точно так же, как к массиву. р>
Почему бы вам просто не использовать NSArray
или NSMutableArray
с NSInteger
с?Эти классы массивов имеют переменную длину и их гораздо проще использовать.
Это приведет к
- (void)testCall: (NSArray *) arr {
NSLog(@"cell value is %u", [[arr objectAtIndex:1] objectAtIndex:1]);
}
(Конечно, вам также придется определить testarr с помощью NSArray.)
Если вы Действительно хотите использовать массивы C, сделав аргумент метода указателем на целое число с
- (void)testCall: (int*) arr {
вероятно, будет работать (остальная часть кода останется прежней).
вызов
int testarr[3][3] = {
{1,1,1},
{1,0,1},
{1,1,1}
};
[self testCall: (int *)testarr];
функция
- (void)testCall: (int *) arr
{
int (*V_arr)[3] = (int(*)[3])arr;
NSLog(@"cell value is %u",V_arr[1][1]);
}