У меня есть этот фрагмент кода:
int main()
{
int first[3][3] = { {0, 1, 2}, {3, 4, 5}, {6, 7, 8}};
int (&second)[9] = reinterpret_cast<int(&)[9]>(first);
for(auto &i: second)
std::cout << i << " ";
void * third = (void *) second;
int (*fourth)[3] = reinterpret_cast<int(*)[3]>(third);
int (&fifth)[3][3] = reinterpret_cast<int(&)[3][3]>(third);
std::cout << first << " "
<< second << " "
<< third << " "
<< fourth << " "
<< fifth << std::endl;
for (int i = 0; i < 3; ++i) {
for (auto &x: fourth[i]) {
std::cout << x << " ";
}
std::cout << std::endl;
}
for (auto &row: fifth) {
for (auto &x: row) {
std::cout << x << " ";
}
std::cout << std::endl;
}
}
В основном я хочу преобразовать int[3][3] в void *, а затем вернуться к int[3][3].
Приведение void * к int(*)[3] работает нормально — отображаются все элементы. Однако приведение к int(&)[3][3] не работает, а значение пятого отличается, напечатанные с первого по четвертый дают одинаковое значение.
Есть ли правильный способ преобразовать void* в многомерный массив?
Хорошо, это звучит разумно. Как и в коде, я хотел использовать стиль С++ 11 для более чем двухмерного массива, но приведение от void * к int (*) [3] также нормально.
Это не относится к вашему вопросу, но ваш использовать из second
имеет неопределенное поведение.
Учитывая float f;
, reinterpret_cast<int&>(f)
создает lvalue типа int
, которое ссылается на f
. По аналогии,
float f,*fp=&f;
do_something(reinterpret_cast<int&>(fp));
передает lvalue, относящееся к fp
, а не f
. Так что в вашем случае fifth
относится к самому third
, а не к first
или вымышленному int[9]
, на который ссылается second
и чей адрес хранится в third
.
Актерский состав, который вы хотите, выглядит так
void *v=&first;
auto &fifth=*reinterpret_cast<int(*)[3][3]>(v);
согласно clang мы получаем предупреждения:
warning: reinterpret_cast from 'int [3][3]' to 'int (&)[9]' has undefined behavior
иwarning: reinterpret_cast from 'void *' to 'int (&)[3][3]' has undefined behavior
Ваше приведение кfourth
правильное - зачем вам ссылка?