Top.Mail.Ru
Ответы

Можно ли работать с указателями в обход помощи компилятора С++?

Вопрос скорее теоретический.

Насколько я понимаю, данные о типе указателя хранятся в метаданных компилятора, а для системы без разницы, будь то int* или int** - и так, и так 8 байт выделяется на 64-битных системах для хранения адреса.

Из этого вопрос, можно ли как-то в обход компилятора использовать такой синтаксис:

12
 int* myArr = new int* [5]; 
for (int i = 0; i < 5; i++) { myArr[i] = new int[5]; } 

Ведь по сути дела системе без разницы, ей главное в куче найти место, где будут свободны 8*5 = 40 байт. А в эти 40 байт опять можно по 5 адресов памяти поместить.
При этом, например, разиминовывать так:

1
 *(*(myArr+1)+3) = 3 

Что тоже самое:

1
 myArr[1][3] = 3; 
По дате
По рейтингу
Аватар пользователя
Новичок
9мес

Первое, что бросается в глаза, это ошибка компиляции следующего кода:

1
 int* myArr = new int* [5]; // Ошибка – требуется двойной указатель 

Но дело даже не в этом. С++ бурно развивается последние полтора десятка лет и всё для того, чтобы полностью уйти от такого синтаксиса. Например, следующий код, написанный в стиле C++11, позволяет уйти от такой ошибки:

1
 auto myArr = new int* [5]; 

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

Аватар пользователя
Мудрец
9мес

Ну вообще ты можешь выделить любую память и тайпкастить её как хочешь. Или я не понял вопроса.

Аватар пользователя
Просветленный
9мес

Ничего не понял, чего ты хочешь...
В С++ есть тип данных "указатель", а не "указатель на ....". То, на что он указывает лишь определяет размер смещения при итерировании. А один указатель к другому всегда можно привести. Например,

1234567891011121314151617181920
 #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; 
}
 
Аватар пользователя
Гений
9мес

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