2013-09-17 2 views
0

Каков метод задания позиции в 2D-массиве. Я не имею в виду получение значения через subscriptip, но аналогично 1D массиву, где с помощью указателя можно использовать оператор + и перейти в эту позицию.Указание конкретной позиции в 2D-массиве

Например, если у меня есть массив A размера 4, я могу перейти к третьему элементу на A + 2.

Как бы это сделать, когда у меня есть 2D-массив?

+0

Вы можете сделать то же самое, но зачем вам? –

+1

A + rownum * ROWSIZE + colnum – bspikol

+1

@bspikol: Нет, это неверно. Это даст вам указатель достаточно далеко от массива (в зависимости от значений rownum и ROWSIZE), и он будет неправильного типа (он будет указателем на массив из T вместо указателя на T) –

ответ

0

Разъязыванием разговора на один уровень за раз. Для массива 2D и 3D массива:

#include <cstdio> 

int A[2][2]; 

int B[2][2][2]; 

int main() { 
    // Set A[1][1] to 2 
    *(*(A+1) + 1) = 2; 
    printf("%d\n", A[1][1]); 

    // Set B[1][1][1] to 3 
    *(*(*(B+1) + 1) + 1) = 3; 
    printf("%d", B[1][1][1]); 
} 

В общем *(...*(*(array_of_N_dimensions + D1) + D2) ... + DN) обеспечит вам доступ к array_of_N_dimensions[D1][D2]...[DN].

2

Где A - массив, R - это строка, а C - столбец.

*(A + R) + C 

дает адрес A[R][C]

+0

Это будет работать SOMETIMES, в зависимости от того, как был выделен массив. См. Мой ответ ниже. – Michael

+1

@Michael: Если у вас есть вторая учетная запись, вы не отправили ответ. –

+0

Извините, Бенджамин был слишком медленным на клавиатуре, сейчас он. – Michael

1

Да, вы правы. Вы можете получить доступ к элементу, умножив размер строки на размер столбца и добавив индекс столбца.

Предположит, целочисленный массив является arr[NUMBER_OF_ROWS][NUMBER_OF_COLUMNS], то вы можете получить доступ к arr[ROW_INDEX][COLUMN_INDEX] элементу как:

int num = *((int *)arr + ROW_INDEX * NUMBER_OF_COLUMNS + COLUMN_INDEX); 
1

вопрос неясен, но вот некоторые мысли.

В языке нет многомерных массивов, поддерживаются только одномерные массивы с некоторыми дополнительными гарантиями. То, что обычно называют двумерным массивом, представляет собой массив 1D объектов массива типа данного типа. Дополнительные гарантии - это функции смежности и выравнивания: каждый элемент массива смежна со следующим элементом в массиве, а массив и первый элемент выравниваются.

Массивы имеют тенденцию к распада на указатель на первый элемент, и вы можете использовать арифметику указателей, чтобы перейти к следующему элементу в массиве, который является тем, что позволяет синтаксис A + 2 значение: &A[0] + 2 или указатель, является результатом добавления 2 в первый (нулевой) элемент в массиве. Но распад - это только верхний уровень.

Гарантии, изложенные до того, как вы можете использовать массив, как если бы он был указателем на первый элемент, и этот элемент находится в том же месте, что и сам массив. Применяя это рекурсивно к вложенному массиву, который вы можете получить на следующее:

int array[10][10]; 
// array is an array of 10 arrays of 10 int 
// array[0] is an array of 10 int, the first subarray 
// array[0][0] is an int, the first element of the subarray 
int *p = &array[0][0]; 
int *q = p + 10;   // One beyond the first subarray: pointer to the first 
          // element of the second subarray. 
int *r = p + 10*row + col; // pointer to the col-th element inside the row-th subarray 
          // equivalent to &array[row][col] 
+0

Мой комментарий для ответа Бенджамина также применим и здесь: это будет работать только в том случае, если вы уверены, что массив был объявлен именно так, и объявление никогда не изменится. – Michael

+0

Хотя я не ожидаю, что какой-либо компилятор когда-либо сделает что-либо иное, чем то, что мы оба ожидаем в этом случае, разве это не технически неопределенное поведение для выполнения арифметики на указателе, которое приводит к результату, который выходит за пределы массива в который вступил исходный указатель? Так, например, 'p' начинается внутри' array [0] ', а затем' p + 10' приводит к указателю вне 'array [0]'. Я думал, что это UB? –

+0

@BenjaminLindley: Не согласен. Хотя в стандарте нет прямой цитаты, которая утверждает, что она действительна, поведение гарантировано и четко определено. Стандарт задает макет двух массивов и что ограничения компоновки подразумевают, что последний элемент первого подмассива смежна с первым элементом второго подмассива, что означает, что при указании на первый вы можете достигнуть второго путем увеличения указатель на 1. –

-2

2-мерные массивы хранятся строки после строки в памяти, так что вы можете получить доступ к A[i][j] используя индексA+i*N+j где N является длиной строки.

+1

Нет, вы определенно не можете получить доступ к 'A [i] [j]', используя это выражение. –

+0

Уверен, опечатка, исправлена ​​ – dkrikun

+0

Я даже не заметил опечатку до тех пор, пока я не отправил комментарий. Это все еще неправильно. См. Мой комментарий к bspikol под оригинальным вопросом. –

0

Вот вам код для самообучения. Надеюсь, это поможет.

#include <iostream> 

int main() 
{ 
    int a[2][2]; 

    a[0][0] = 1; 
    a[0][1] = 2; 
    a[1][0] = 3; 
    a[1][1] = 4; 


    for (int i=0; i < 4; ++i) 
    { 
     std::cout << *(*a+i) << std::endl; 
    } 

    return 0; 
} 
0

Другие ответы, основываясь на арифметику указателей, технически правильно, но только если вы уверены, что ваш массив выделяется как A [строк] [перевалы]. Это очень часто бывает не так, и даже если вы реализуете свой массив, вы не можете быть уверены, что другой разработчик не будет реорганизовывать его. В тот момент, когда другой разработчик меняет тип A [rows] [cols] на вектор < vector < type>> Ваш код сломается.

Поэтому я бы посоветовал НЕ использовать арифметику указателей по строкам. Если вас беспокоит производительность - не делайте этого: компилятор автоматически использует арифметику указателя для доступа к элементам массива, где это применимо. Что еще более важно, компилятор не будет использовать арифметику указателя, если это не применимо.

+0

Вектор - это * не * массив, а 'vector >' имеет совершенно другую структуру памяти, чем массив массивов.Общая реализация многомерной матрицы обычно представляет собой один элемент «vector <>» с элементами 'rows * cols' и арифметикой указателя внутри класса, который управляет объектом. Я не думаю, что я бы использовал 'vector >' как замену массиву из нескольких dims (единственное преимущество 'vector >' в том, что он может быть зазубренным, но это не относится к массивам! –

+0

Ну, это был всего лишь пример рефакторинга, который нарушил бы арифметический код указателя. Вместо вектора <вектор < type >> A он должен был быть не_континентальным_контейнером < type > А. :) – Michael

Смежные вопросы