Я играю с указателями и наткнулся на эту проблему. Как и в этом вопрос, мне нужна общая сигнатура метода для функции foo, поэтому я выбрал void * input в качестве параметра. По причинам тестирования я применил указатель void к указателю int **, чтобы использовать его как 2D-массив.
#include <stdio.h>
#include <stdlib.h>
void * foo(void *input, size_t mySize)
{
for (size_t i = 0; i < mySize; ++i)
{
for (size_t j = 0; j < mySize; ++j)
{
((int **)input)[i*mySize][j] = 10*i+j;
}
}
return input;
}
int main(int argc, char const *argv[])
{
size_t const mySize = 10;
void * myMemory, * testPtr;
myMemory = malloc(mySize * mySize * sizeof(int));
testPtr = foo(myMemory, mySize);
free(testPtr);
return 0;
}
Теперь я подумал, что использование оператора [] будет таким же, как добавление int к указателю, например. что ((int **)input[i][j] будет таким же, как `((int **) input) + i + j
Но доступ к входному массиву в foo segfaults и использование gdb показывает мне
(gdb) p ((int **)input)[i][j]
Cannot access memory at address 0x0
(gdb) p ((int **)input)+i+j
$25 = (int **) 0x405260
так что очевидно есть разница. И поэтому я запутался.
Вам нужно рассматривать его как массив 2d, а не использовать его как массив 2d.
Учтите, что int a[A][B] означает массив int[B]. Но если вы приведете указатель void* к другому указателю int**, откуда (TH) компилятор должен знать, какое измерение массива вы имеете в виду ...
((int **)input[i][j] - это двухуровневый указатель доступа, эквивалентный *(*((int**)input + i) + j) (обратите внимание, что каждый [] включает в себя уважение). Вы, вероятно, захотите (int*)[i + j].
Относительно общей функции (интерфейса): может быть, вы могли бы взглянуть на qsort(). Это C-ish версия универсальной функции сортировки. Я имею в виду, в частности, как они описывают массив и элементы, переданные для создания функции «в общем». Конечно, в стандартной библиотеке C есть и другие примеры - qsort() был только первым, что пришло мне в голову.
Пожалуйста, прочтите stackoverflow.com/questions/4470950/… и stackoverflow.com/questions/7586702/…





Вы выделили одномерный массив с элементами mySize * mySize. int ** - это массив указателей на int, вам нужно
int **array2d;
int *p;
array2D = malloc(ROWS * sizeof(int*) + ROWS * COLUMNS * sizeof(int));
p = (int*) &array2d[ROWS];
for (size_t i = 0; i < ROWS; ++i)
array2d[i] = &p[i * COLUMNS];
теперь может работать array2d [row] [column].
Или, как уже было предложено, используйте одномерный массив и формулы массива [строка * COLUMNS + столбец].
Хотя массивы и указатели похожи, они не совпадают.
Массив - одномерный или многомерный - представляет собой непрерывный фрагмент памяти, содержащий определенный тип данных. Например, int arr [10] объявляет arr как 10 непрерывных int в памяти. int multi_arr[5][10] объявляет multi_arr как 5 массивов из 10 непрерывных int в памяти.
Кроме того, имя arr будет базовым адресом этого массива, и его передача функции будет такой же, как передача &arr[0].
Но на этом сходство заканчивается. Многомерный массив (технически) не может быть преобразован в указатель на указатель, а затем обратно.
Если вышеупомянутый arr указывает на блок int, то разыменование первого измерения int ** ptr приведет вас к блоку указателей на int. Разыменование тот не приведет вас глубже в этот блок, как это сделал бы многомерный массив, скорее, он мог бы указывать куда угодно.
((int **)input)[i*mySize][j]Боюсь, это вряд ли сработает. Почему не просто((int*)input)[i * mySize + j] = 10 * i + j;?