|
Программирование >> Аргументация конструирования
надейтесь, что, написав сложное и запутанное выражение на C++, вы сэкономите несколько машинных команд. В C++ нет прямой связи между количеством команд в исходном и конечном коде. Сравните два набора команд в приведенном ниже фрагменте. / / выражение *pszArray++ = ХО; / /и выражение *pszArray2 = \0; pszArray2 ггау2 + 1; после компиляции могут давать одинаковое количество машинных инструкций Во времена примитивных компиляторов, которые не оптимизировали код, первый вариант вызвал бы использование меньшего количества машинных команд. Однако современным оптимизирующим компилятором в обоих случаях будет сгенерирован идентичный код. Операции с указателями других типов Нетрудно сообразить, что szTarget + n указывает на элемент если szTarget является массивом однобайтовых значений. Если szTarget начинается но адресу 0x100, то шестой элемент массива будет находиться по адресу Однако положение элемента в массиве становится не столь очевидным, если массив состоит из элементов типа irn:, которые занимают по четыре байта каждый. Если первый элемент такого массива находится по адресу 0x100, то шестой будет находиться по адресу 0x114 {0x100 + (5*4) = 0x114). Но, к счастью для нас, выражение вида array + n будет всегда указывать на элемент [n], независимо от размера элемента, поскольку в таком выражении C++ самостоятельно учитывает длину элемента. И вновь обратимся за аналогией к моему дому. Третий дом от 123 Main Street будет иметь адрес 126 Main Street, независимо от размеров стоящих на Main Streel домов. Отличия между указателями и массивами Есть и несколько отличий в использовании массива и указателя. Во-перв1х, объявление массива вызывает выделение памяти для всего массива, тогда как объявление указателя не вызывает выделения памяти для массива. void arrayPointerО выделение памяти для 12 8 символов char charArray[128]; выделение памяти для но не для объекта, на который он указывает char* pArray; В этом примере для charArray выделяется байт, а для - четыре, ров- но столько, сколько необходимо для хранения указателя. Приведенная ниже функция работать не будет. void arrayVsPointer{) этот фрагмент будет работать нормально char CharArray[12 8] ; CharArray[10] = О; * (charArray +10) = О; этот фрагмент не будет работать так, как надо char* pArray; pArray[10] = О; * {pArray + 10} ; Выражения charArray [ 10 ] и *(charArray + Ю) с позиции компилятора эквивалентны и вполне законны. Те же выражения с использованием pArray являются бессмысленными. Несмотря на то что для C + + они являются законными, pArray не инициализирован как указатель на массив, а значит, память была выделена только для указателя. Таким образом, рАггау[10) и * (рАггау + 10) указывают на неизвестные и непредсказуемые значения. Неправильно инициализированные указатели обычно вызывают ошибку нарушения сегмента (segment violation). Эту ошибку вы иногда встречаете в повседневной работе со своими любимыми приложениями в своей любимой (а может, и не очень) операционной системе. Вторым отличием между указателями и индексами массива является то, что cha-rArray - константа, тогда как pArray - нет. Приведенный ниже цикл for, который должен инициализировать значения элементов массива, тоже не будет работать. void arrayVsPointerО char CharArray [10] ; for ;int i = 0; i < 10; i++) charArray Л0; эта строка имеет смысл... } charArray++; ... а эта нет Выражение charArray++ имеет не больше смысла, чем 10++. Правильно следует написать так: void arrayVsPointerО char CharArray[10]; char* pArray = charArray; for (int i - 0; i < 10; i++) этот вариант будет работать так как надо OSisUUeHue и испсльзоЛание масси£а€ ifKosaMeAeu Если есть указатели на массивы, можно предположить, что существуют и массивы указателей. Именно их мы сейчас и рассмотрим. Поскольку массив может содержать данные любого типа, он может состоять и из указателей. Массив указателей объявляется так: int* pints[10]; Таким образом, элемент [0] является указателем на переменную типа int. Следовательно, приведенный ниже код корректен: voi fn () ( int nl; int* pints [3]; pints [0] = snl; plntstO] = 1; Как и этот: void fn() int п1,п2,пЗ; int* plnts[3] = {snl, &n2, £пЗ,}; for (int i = 0;i < 3; i + + ) pints [i] = 0; И даже этот: void fnO int п1,п2,пЗ; int* pints[3] = {(new int), (new int), (new int)}, for (int i = 0;i < 3; i++5 { *plnts [i] = 0; В последнем варианте память под переменные выделяется из так называемой кучи, т.е. доступной программе памяти компьютера. Массивы указателей чаще всего используются для работы с массивами строк. Приведенные далее примеры показывают, почему это удобно. Использование массивов строк Поскольку C++ поддерживает массивы указателей, значит, он должен поддерживать и массивы указателей на массивы. C++ действительно поддерживает такие конструкции, при этом количество повторений в принципе не офаничено (можно создать массив указателей на массив указателей на массив указателей...). Отдельный интерес представляют массивы указателей на строки. (Не забывайте, что строка является массивом символов.) Допустим, мне понадобилась функция, возвращающая название месяца по его номеру. Например, если этой функции передать число 1, она вернет название первого месяца - Январь . Номер месяца будет считаться неправильным, если он окажется меньше 1 или больше 12. Эту функцию можно написать следующим образом: - возвращает название месяца char* int2month(int nMonth) char* pszReturnValue; switch(nMonth)
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |