Кастинг между многомерными и одномерными массивами - PullRequest
3 голосов
/ 11 сентября 2008

Это пришло из этого ответа на мой предыдущий вопрос . Гарантируется ли компилятором обработку array[4][4] так же, как array[16]?

Например, будет ли безопасным любой из приведенных ниже вызовов api_func()?

void api_func(const double matrix[4][4]);

// ...

{
  typedef double Matrix[4][4];

  double* array1 = new double[16];
  double array2[16];

  // ...

  api_func(reinterpret_cast<Matrix&>(array1));
  api_func(reinterpret_cast<Matrix&>(array2));
}

Ответы [ 6 ]

3 голосов
/ 11 сентября 2008

Из стандарта C ++, ссылаясь на оператор sizeof:

При применении к массиву результатом является общее количество байтов в массиве. Это означает, что размер массива n элементов в n раз превышает размер элемента.

Исходя из этого, я бы сказал, что double[4][4] и double[16] должны иметь одинаковое базовое представление.

Т.е., дано

sizeof(double[4]) = 4*sizeof(double)

и

sizeof(double[4][4]) = 4*sizeof(double[4])

тогда у нас есть

sizeof(double[4][4]) = 4*4*sizeof(double) = 16*sizeof(double) = sizeof(double[16])

Я думаю, что совместимый со стандартами компилятор должен был бы реализовать их одинаково, и я думаю, что это не то, что компилятор случайно сломал бы. Стандартный способ реализации многомерных массивов работает, как и ожидалось. Нарушение стандарта потребовало бы дополнительной работы, вероятно, без выгоды.

Стандарт C ++ также гласит, что массив состоит из смежно расположенных элементов, что исключает возможность делать что-либо странное с помощью указателей и отступов.

2 голосов
/ 11 сентября 2008

Я не думаю, что есть проблема с заполнением, вызванная наличием многомерного массива.

Каждый элемент в массиве должен удовлетворять требованиям заполнения, предъявляемым архитектурой. Массив [N] [M] всегда будет иметь то же представление в памяти, что и один из [M * ​​N].

1 голос
/ 12 сентября 2008

@ Конрад Рудольф:

Я перепутал эти два (основной ряд / основной столбец), но я знаю это: он четко определен.

Например,

int x [3] [5] - это массив размера 3, элементы которого являются массивами типа int 5. (§6.5.2.1) Добавление всех правил из стандарта, касающихся массивов, адресации и т. Д. Вы получаете, что второй индекс ссылается на последовательные целые числа, тогда как первый индекс будет ссылаться на последовательные 5-целые объекты. (Таким образом, 3 - это большее число; у вас есть 5 значений между x [1] [0] и x [2] [0].)

1 голос
/ 11 сентября 2008

Каждый элемент массива должен быть последовательно расположен в памяти компилятором. Эти два объявления, в то время как разные типы, являются одной и той же структурой памяти.

0 голосов
/ 11 сентября 2008

Более важный вопрос: вам действительно нужно выполнить такой актерский состав?

Хотя вы могли бы быть в состоянии обойтись без него, он все равно будет более читабельным и обслуживаемым, чтобы его вообще избежать. Например, вы можете последовательно использовать double [m * n] в качестве фактического типа, а затем работать с классом, который упаковывает этот тип, и, возможно, перегружает оператор [] для простоты использования. В этом случае вам также может понадобиться промежуточный класс для инкапсуляции одной строки - так, чтобы код, подобный my_matrix [3] [5], все еще работал как ожидалось.

0 голосов
/ 11 сентября 2008

Я бы беспокоился о добавлении отступов для таких вещей, как Matrix [5] [5], чтобы выровнять каждое слово строки, но это могло быть просто моим собственным суеверием.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...