Можно ли работать с указателями в обход помощи компилятора С++?
Вопрос скорее теоретический.
Насколько я понимаю, данные о типе указателя хранятся в метаданных компилятора, а для системы без разницы, будь то int* или int** - и так, и так 8 байт выделяется на 64-битных системах для хранения адреса.
Из этого вопрос, можно ли как-то в обход компилятора использовать такой синтаксис:
int* myArr = new int* [5];
for (int i = 0; i < 5; i++) { myArr[i] = new int[5]; }
Ведь по сути дела системе без разницы, ей главное в куче найти место, где будут свободны 8*5 = 40 байт. А в эти 40 байт опять можно по 5 адресов памяти поместить.
При этом, например, разиминовывать так:
*(*(myArr+1)+3) = 3
Что тоже самое:
myArr[1][3] = 3;
Первое, что бросается в глаза, это ошибка компиляции следующего кода:
int* myArr = new int* [5]; // Ошибка – требуется двойной указатель
Но дело даже не в этом. С++ бурно развивается последние полтора десятка лет и всё для того, чтобы полностью уйти от такого синтаксиса. Например, следующий код, написанный в стиле C++11, позволяет уйти от такой ошибки:
auto myArr = new int* [5];
Для вашей задачи можно было бы использовать вектор векторов из стандартной библиотеки шаблонов, с которым удобно работать такими же стандартными алгоритмами. Но вас интересует не прикладная цель задачи, а какие-то сложные технические детали, которые в приличных местах принято называть костылями парка Юрского периода. Заканчивайте с этим.
Ну вообще ты можешь выделить любую память и тайпкастить её как хочешь. Или я не понял вопроса.
Ничего не понял, чего ты хочешь...
В С++ есть тип данных "указатель", а не "указатель на ....". То, на что он указывает лишь определяет размер смещения при итерировании. А один указатель к другому всегда можно привести. Например,
#include <iostream>
#include <string.h>
int main()
{
unsigned char* pBuffer = new unsigned char[ 2 * sizeof( int ) ];
int* tmp = reinterpret_cast< int* >( pBuffer );
tmp[ 0 ] = 11;
tmp[ 1 ] = 55;
int value = 0;
std::cout<<" Accessing data:\n";
value = tmp[ 0 ];
std::cout << "\t as Int Ptr: tmp[0] = " << value;
memcpy( &value, pBuffer + sizeof( int ), sizeof( int ) );
std::cout << "\n\t from char: " << value;
delete[] pBuffer;
return 0;
}

Для компилятора нельзя писать в обход компилятора. Если требуется какая-то экзотика, делают ассемблерные вставки которые транслируются в машинный код без всяких преобразований.
А тут разве что так:
int* arr = new int[10]; //40 байт не нарушая синтаксис
for (int i=0;i<5;i++) ((int**)arr)[i] = new int[5];