Приведение между многомерными и одномерными массивами

StackOverflow https://stackoverflow.com/questions/55532

  •  09-06-2019
  •  | 
  •  

Вопрос

Это пришло из это ответ на мой предыдущий вопрос.Гарантировано ли, что компилятор обработает 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));
}
Это было полезно?

Решение

Из стандарта 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++ также утверждает, что массив состоит из смежно размещенных элементов, что исключает возможность каких-либо странных действий с использованием указателей и заполнения.

Другие советы

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

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

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

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

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

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top