Пусть имеем статический массив:
short tell[20];
Где:
tell
- адрес первого элемента массива (2-байтный блок).&tell
- адрес целого массива (40-байтный блок).И имеется следующая конструкция, указывающая на массив из 20 элементов типа short:
short (*pas)[20] = &tell
Получившимся типом данных переменной pas является тип: short (*)[20]
. Собственно вопрос, как создать переменную данного типа, и выделить ей память при помощи операции new?
Пример взят из книги: Стивен Прата - Язык программирования C++ (6 издание). Стр. 182.
Если у вас есть объявление массива вида
T a[N];
где T
- это некоторый тип, а N
- это число элементов в массиве, то указатель на первый элемент массива будет иметь тип T *
. Например
T *p = a;
После этого определения указатель p
указывает на первый элемент массива a
.
Чтобы выделить динамически память для массива, аналогичного массиву, определенному выше, вы можете записать
T *p = new T[N];
Здесь элемент массива имеет тип T
, а p
как и выше показывает на первый элемент динамически выделенного безыменного массива..
Теперь представим, что T
это алиас для типа short[20]
, например
typedef short T[20];
Тогда ранее показанные объявления для указателя могут быть записаны как
T *p = &a;
и
T *p = new T[1];
Если снова вернуться к исходному типу short[20]
, то получим
short( *p )[20] = &a;
и
short( *p )[20] = new short[1][20];
Последнее предложение означает, что выделяется массив из одного элемента (вы можете выделять массив из произвольного числа элементов в соответствии с вашей задачей), элементами которого в свою очередь являются массивы из 20 элементов типа short
.
Имейте в виду, что когда используется так называемая арифметика указателей, то значение указателя меняется на значение кратное sizeof( T )
Поэтому если вы, например, объявите указатель как
short( *p )[20] = &a;
где T
эквивалентно short[20]
, то после применения, например, инкремента к этому указателю
++p;
указатель будет содержать адрес сразу же после последнего элемента массива a
.
Ну, и напоследок пример работы с таким указателем.
#include <iostream>
#include <iomanip>
#include <algorithm>
#include <numeric>
#include <iterator>
const size_t N = 20;
short ( * create_2D_array( size_t n ) )[N]
{
short ( *p )[N] = new short[n][N];
return p;
}
int main()
{
short a[N];
std::iota( std::begin( a ), std::end( a ), 1 );
for ( short x : a ) std::cout << std::setw( 2 ) << x << ' ';
std::cout << std::endl;
short ( *p )[N] = create_2D_array( 1 );
std::iota( std::reverse_iterator<short *>( *p + N ),
std::reverse_iterator<short *>( *p ), 1 );
for ( short x : *p ) std::cout << std::setw( 2 ) << x << ' ';
std::cout << std::endl;
std::cout << std::endl;
std::swap( a, *p );
for ( short x : a ) std::cout << std::setw( 2 ) << x << ' ';
std::cout << std::endl;
for ( short x : *p ) std::cout << std::setw( 2 ) << x << ' ';
std::cout << std::endl;
delete [] p;
return 0;
}
Вывод программы на консоль
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1
20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
Вообще-то и tell
, и &tell[0]
, и &tell
- это все одна и та же сущность, адрес, с которого начинается блок памяти, выделенный для массива...
typedef short array[20];
short * a = new array;
Здесь мы описываем тип массива из 20 short
, и создаем его динамически, возвращая указатель на начало блока с ним. Работаем с ним, как с обычным массивом, типа
for(short i = 0; i < 20; ++i)
{
a[i] = i;
}
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
Виртуальный выделенный сервер (VDS) становится отличным выбором
Добрый вечерНе могу понять действия рекурсивной функции при нахождении числа Фибоначчи
Пытаюсь с QByteArray получить указатель на данные с помощью data(), ругается: