Страницы

Поиск по вопросам

воскресенье, 1 декабря 2019 г.

Указатель на массив C++

#cpp #массивы #указатели


Пусть имеем статический массив:

short tell[20];


Где:


tell - адрес первого элемента массива (2-байтный блок).
&tell - адрес целого массива (40-байтный блок).


И имеется следующая конструкция, указывающая на массив из 20 элементов типа short:

short (*pas)[20] = &tell


Получившимся типом данных переменной pas является тип: short (*)[20]. Собственно
вопрос, как создать переменную данного типа, и выделить ей память при помощи операции new?

Пример взят из книги: Стивен Прата - Язык программирования C++ (6 издание). Стр. 182.
    


Ответы

Ответ 1



Если у вас есть объявление массива вида 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 #include #include #include #include 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( *p + N ), std::reverse_iterator( *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

Ответ 2



Вообще-то и tell, и &tell[0], и &tell - это все одна и та же сущность, адрес, с которого начинается блок памяти, выделенный для массива... typedef short array[20]; short * a = new array; Здесь мы описываем тип массива из 20 short, и создаем его динамически, возвращая указатель на начало блока с ним. Работаем с ним, как с обычным массивом, типа for(short i = 0; i < 20; ++i) { a[i] = i; }

Комментариев нет:

Отправить комментарий