Глава 7 Указатели. План 7.1Introduction 7.2Pointer Variable Declarations and Initialization 7.3Pointer Operators 7.4Calling Functions by Reference 7.5Using.

Презентация:



Advertisements
Похожие презентации

Advertisements

1. Определить последовательность проезда перекрестка
Таблица умножения на 8. Разработан: Бычкуновой О.В. г.Красноярск год.
Фрагмент карты градостроительного зонирования территории города Новосибирска Масштаб 1 : 6000 Приложение 7 к решению Совета депутатов города Новосибирска.
Фрагмент карты градостроительного зонирования территории города Новосибирска Масштаб 1 : 6000 Приложение 7 к решению Совета депутатов города Новосибирска.
1 Знаток математики Тренажер Таблица умножения 2 класс Школа 21 века ®м®м.
Символы и строки 1. Содержание 8.1Введение 8.2Основы Строк и Символов 8.3Библиотека работы со строками 8.4Преобразование строк 8.5Стандартная библиотека.
ОДНОМЕРНЫЕ МАССИВЫ. РАБОТА С ЭЛЕМЕНТАМИ СТРУКТУРИРОВАННЫЕ ТИПЫ ДАННЫХ.
Урок повторения по теме: «Сила». Задание 1 Задание 2.
Лекция 9 Функции. Массивы-параметры функции Передача массива в функцию Пример: void array_enter(int a[], int size) { int i; for (i = 0; i < size; i++)
1 Глава 2 Введение в программирование на С Введение 2.2 Простая программа на C Program: Печатаем строку текста 2.3 Другая простая программа на C:
Фрагмент карты градостроительного зонирования территории города Новосибирска Масштаб 1 : 4500 к решению Совета депутатов города Новосибирска от
Прототип задания В3 Площади фигур. Задание 1 Задание 2.
УКАЗАТЕЛИ. Переменная - это именованная область памяти с заданным типом. [=значение]; int a; //Переменная типа integer с именем a int b=2;// Переменная.
Матемтааки ЕТ СТ 2 класс Шипилова Наталия Викторовна учитель начальных классов, ВКК Шипилова Наталия Викторовна учитель начальных классов, ВКК.
Урок-обобщение (7 класс – алгебра) МОУ "СОШ 45 г. Чебоксары" Кабуркина М. Н.1.
1 Знаток математики Тренажер Таблица умножения 3 класс Школа России Масько Любовь Георгиевна Муниципальное общеобразовательное учреждение средняя общеобразовательная.
П РОТОТИП ЗАДАНИЯ В3 В МАТЕРИАЛАХ ЕГЭ Площади фигур.
Лекция 2 Раздел 2.1 Windows Phone Темы раздела 3.
Анализ результатов краевых диагностических работ по русскому языку в 11-х классах в учебном году.
Транксрипт:

Глава 7 Указатели

План 7.1Introduction 7.2Pointer Variable Declarations and Initialization 7.3Pointer Operators 7.4Calling Functions by Reference 7.5Using the const Qualifier with Pointers 7.6Bubble Sort Using Call by Reference 7.7Pointer Expressions and Pointer Arithmetic 7.8The Relationship between Pointers and Arrays 7.9Arrays of Pointers 7.10Case Study: A Card Shuffling and Dealing Simulation 7.11Pointers to Functions

7.1Введение Указатели Указатели Мощное средство, но надо быть аккуратным Мощное средство, но надо быть аккуратным Похожи на вызов по ссылке Похожи на вызов по ссылке Тесно связаны с массивами и строками Тесно связаны с массивами и строками

7.2Объявление и инициализация указателя Указатель на переменную Указатель на переменную Содержит адрес ячейки памяти как значение Содержит адрес ячейки памяти как значение Нормальные переменные содержат определенное значение (прямая ссылка) Нормальные переменные содержат определенное значение (прямая ссылка) Указатели содержат адрес переменной, которая содержит определенное значение (косвенная ссылка) Указатели содержат адрес переменной, которая содержит определенное значение (косвенная ссылка) Косвенная – адресуется значением указателя Косвенная – адресуется значением указателя count 7 7 countPtr

7.2Объявление и инициализация указателя Объявление указателя Объявление указателя * используется с переменными * используется с переменными int *myPtr; Объявляем указатель на int (указатель типа int * ) Объявляем указатель на int (указатель типа int * ) Несколько указателей требуют * перед каждым объявлением переменной Несколько указателей требуют * перед каждым объявлением переменной int *myPtr1, *myPtr2; Можно объявлять указатели на любой тип данных Можно объявлять указатели на любой тип данных Инициализируем указатели 0, NULL, или адресом Инициализируем указатели 0, NULL, или адресом 0 или NULL – указывает на пустоту ( NULL предпочтительнее) 0 или NULL – указывает на пустоту ( NULL предпочтительнее)

7.3Операции с указателем & (адресный оператор) & (адресный оператор) Возвращает адрес операнда Возвращает адрес операнда int y = 5; int *yPtr; yPtr = &y; // yPtr = адрес y yPtr указывает на y yPtr y 5 yptr y 5 Адрес y это значение yptr

7.3Операции с указателем * (разыменовывание указателя) * (разыменовывание указателя) Возвращает синоним/алиас того, на что указывает указатель Возвращает синоним/алиас того, на что указывает указатель *yptr возвращает y (потому что yptr указывает на y ) *yptr возвращает y (потому что yptr указывает на y ) * может использоваться при присваивании * может использоваться при присваивании *yptr = 7; // меняем y на 7 Разыменованный указатель (операнд * ) должен быть lvalue (не константа) Разыменованный указатель (операнд * ) должен быть lvalue (не константа) * и & инверсивные * и & инверсивные Они отменяют друг друга Они отменяют друг друга

1. Определение переменных 2 Инициализация переменных 3. Печать Результат 1/* Fig. 7.4: fig07_04.c 2 Using the & and * operators */ 3#include 4 5int main() 6{6{ 7 int a; /* a is an integer */ 8 int *aPtr; /* aPtr is a pointer to an integer */ 9 10 a = 7; 11 aPtr = &a; /* aPtr set to address of a */ printf( "The address of a is %p" 14 "\nThe value of aPtr is %p", &a, aPtr ); printf( "\n\nThe value of a is %d" 17 "\nThe value of *aPtr is %d", a, *aPtr ); printf( "\n\nShowing that * and & are inverses of " 20 "each other.\n&*aPtr = %p" 21 "\n*&aPtr = %p\n", &*aPtr, *&aPtr ); return 0; 24} The address of a is 0012FF88 The value of aPtr is 0012FF88 The value of a is 7 The value of *aPtr is 7 Proving that * and & are complements of each other. &*aPtr = 0012FF88 *&aPtr = 0012FF88 Адрес a это значение aPtr. aPtr указывает на a, так что *aPtr возвращает a. Пример как * и & отменяют друг друга

7.4Вызов функции по ссылке Вызов по ссылке с указателем в качестве аргумента Вызов по ссылке с указателем в качестве аргумента Передаем адрес аргумента используя оператор & Передаем адрес аргумента используя оператор & Можно менять настоящее размещение в памяти Можно менять настоящее размещение в памяти Массивы не передаются с &, потому что имя массива - это уже указатель Массивы не передаются с &, потому что имя массива - это уже указатель

7.4Вызов функции по ссылке оператор * оператор * Используется как алиас для переменной внутри функции Используется как алиас для переменной внутри функции void double( int *number ) { *number = 2 * ( *number ); } *number используется как имя передаваемой переменной *number используется как имя передаваемой переменной

1 Прототип функции 1.1 Инициализация переменных 2. Вызов функции 3. Определение функций Результат 1/* Fig. 7.7: fig07_07.c 2 Cube a variable using call-by-reference 3 with a pointer argument */ 4 5#include 6 7void cubeByReference( int * ); /* prototype */ 8 9int main() 10{ 11 int number = 5; printf( "The original value of number is %d", number ); 14 cubeByReference( &number ); 15 printf( "\nThe new value of number is %d\n", number ); return 0; 18} 19 20void cubeByReference( int *nPtr ) 21{ 22 *nPtr = *nPtr * *nPtr * *nPtr; /* cube number in main */ 23} The original value of number is 5 The new value of number is 125 Адрес number передается - cubeByReference ожидает указатель (адрес переменной). Внутри cubeByReference, используется *nPtr ( *nPtr это число). Прототип функции, получающей указатель на целое ( int * ).

7.5Использование модификатора const с указателями const переменная const переменная Переменную нельзя изменить Переменную нельзя изменить Используйте const если функция не требует изменять переменную Используйте const если функция не требует изменять переменную Попытка изменить переменную с const вызовет ошибку Попытка изменить переменную с const вызовет ошибку

7.5Использование модификатора const с указателями const указатель const указатель Указывает на постоянное место в памяти Указывает на постоянное место в памяти Должно быть инициализировано при объявлении: Должно быть инициализировано при объявлении: int *const myPtr = &x; int *const myPtr = &x; Тип int *const – постоянный указатель на int Тип int *const – постоянный указатель на int const int *myPtr = &x; const int *myPtr = &x; Обычный указатель на const int Обычный указатель на const int const int *const Ptr = &x; const int *const Ptr = &x; сonst указатель на const int сonst указатель на const int x может меняться но не *Ptr x может меняться но не *Ptr

1. Объявление переменных 1.1 Объявление const указателя на int 2. Изменение *ptr (что есть x ) 2.1 Попытка изменения ptr 3. Вывод Результат 1/* Fig. 7.13: fig07_13.c 2 Attempting to modify a constant pointer to 3 non-constant data */ 4 5#include 6 7int main() 8{8{ 9 int x, y; int * const ptr = &x; /* ptr is a constant pointer to an 12 integer. An integer can be modified 13 through ptr, but ptr always points 14 to the same memory location. */ 15 *ptr = 7; 16 ptr = &y; return 0; 19} FIG07_13.c: Error E2024 FIG07_13.c 16: Cannot modify a const object in function main *** 1 errors in Compile *** Изменение *ptr разрешено – x это не константа Изменение ptr это ошибка – ptr это константный указатель.

7.6Сортировка пузырьком используя вызов по ссылке Реализация сортировки пузырьком с использованием указателей Реализация сортировки пузырьком с использованием указателей Заменить два элемента Заменить два элемента swap функция должна получать адрес (используя & ) элементов массива swap функция должна получать адрес (используя & ) элементов массива Элементы массива имеют вызов по значению Элементы массива имеют вызов по значению Использование указателей и оператора *, swap может заменять элементы массива Использование указателей и оператора *, swap может заменять элементы массива

7.6Сортировка пузырьком используя вызов по ссылке Псевдокод Псевдокод Инициализируем массив печатаем данные в оригинальном порядке печатаем данные в оригинальном порядке Вызов функции bubblesort печатаем отсортированный массив Определяем bubblesort

7.6Сортировка пузырьком используя вызов по ссылке sizeof sizeof Возвращает размер операнда в байтах Возвращает размер операнда в байтах Для массивов: размер одного элемента * количество элементов Для массивов: размер одного элемента * количество элементов если sizeof( int ) дает 4 байта, тогда если sizeof( int ) дает 4 байта, тогда int myArray[ 10 ]; printf( "%d", sizeof( myArray ) ); Напечатает 40 Напечатает 40 sizeof может применяться с sizeof может применяться с Именами переменных Именами переменных Названия типа Названия типа Константами Константами

1. Инициализация массива 1.1 Объявление переменных 2. Печатаем массив 2.1 Вызываем bubbleSort 2.2 Печатаем массив 1/* Fig. 7.15: fig07_15.c 2 This program puts values into an array, sorts the values into 3 ascending order, and prints the resulting array. */ 4#include 5#define SIZE 10 6void bubbleSort( int *, const int ); 7 8int main() 9{9{ int a[ SIZE ] = { 2, 6, 4, 8, 10, 12, 89, 68, 45, 37 }; 12 int i; printf( "Data items in original order\n" ); for ( i = 0; i < SIZE; i++ ) 17 printf( "%4d", a[ i ] ); bubbleSort( a, SIZE ); /* sort the array */ 20 printf( "\nData items in ascending order\n" ); for ( i = 0; i < SIZE; i++ ) 23 printf( "%4d", a[ i ] ); printf( "\n" ); return 0; 28} 29 30void bubbleSort( int *array, const int size ) 31{ 32 void swap( int *, int * ); Bubblesort получает адрес элементов массива (указатели). Имя массива – это указатель.

3. Определение функции Результат 33 int pass, j; 34 for ( pass = 0; pass < size - 1; pass++ ) for ( j = 0; j < size - 1; j++ ) if ( array[ j ] > array[ j + 1 ] ) 39 swap( &array[ j ], &array[ j + 1 ] ); 40} 41 42void swap( int *element1Ptr, int *element2Ptr ) 43{ 44 int hold = *element1Ptr; 45 *element1Ptr = *element2Ptr; 46 *element2Ptr = hold; 47} Data items in original order Data items in ascending order

7.7Операции с указателями Арифметические операции с указателем Арифметические операции с указателем Инкремент/декремент указателя ( ++ или -- ) Инкремент/декремент указателя ( ++ или -- ) Добавить целое к указателю ( + или +=, - или -= ) Добавить целое к указателю ( + или +=, - или -= ) Можно вычитать указатели друг из друга Можно вычитать указатели друг из друга Операции не имеют смысла, если не выполняются с массивом Операции не имеют смысла, если не выполняются с массивом

7.7Операции с указателями 5 элементов массива int на машине с 4 байтным int 5 элементов массива int на машине с 4 байтным int vPtr указывает на первый элемент v[ 0 ] vPtr указывает на первый элемент v[ 0 ] Допустим адрес = 3000 ( vPtr = 3000 ) Допустим адрес = 3000 ( vPtr = 3000 ) vPtr += 2; установим vPtr в 3008 vPtr += 2; установим vPtr в 3008 vPtr указывает на v[ 2 ] (увеличили на 2), но машина имеет 4х байтный int, так что указатель указывает на адрес 3008 vPtr указывает на v[ 2 ] (увеличили на 2), но машина имеет 4х байтный int, так что указатель указывает на адрес 3008 pointer variable vPtr v[0]v[1]v[2]v[4]v[3] location

7.7Операции с указателями Вычитание указателей Вычитание указателей Возвращает количество элементов из одного в другом. Если Возвращает количество элементов из одного в другом. Если vPtr2 = v[ 2 ]; vPtr = v[ 0 ]; vPtr2 - vPtr дает 2 vPtr2 - vPtr дает 2 Сравнение указателей ( ) Сравнение указателей ( ) Смотрим какой указатель ссылается на более старший по индексу элемент массива Смотрим какой указатель ссылается на более старший по индексу элемент массива Смотрим не ссылается ли указатель на 0 Смотрим не ссылается ли указатель на 0

7.7Операции с указателями Указатели одного типа могут быть присвоены друг другу Указатели одного типа могут быть присвоены друг другу Если тип разный, требуется приведение типов Если тип разный, требуется приведение типов Исключение: указатель на void (тип void * ) Исключение: указатель на void (тип void * ) Базовый указатель, отражает любой тип Базовый указатель, отражает любой тип Преобразование типов не требуется для конвертации указателя в указатель на void Преобразование типов не требуется для конвертации указателя в указатель на void void указатели нельзя разыменовывать void указатели нельзя разыменовывать

7.8Связь между указателями и массивами Массивы и указатели тесно связаны Массивы и указатели тесно связаны Имя массива это как константный указатель Имя массива это как константный указатель Указатели могут выполнять операцию адресации по индексу Указатели могут выполнять операцию адресации по индексу Объявление массива b[ 5 ] и указателя bPtr Объявление массива b[ 5 ] и указателя bPtr Для установки другому такого же значения: Для установки другому такого же значения: bPtr = b; Имя массива ( b ) на самом деле адрес первого элемента массива b[ 5 ] Имя массива ( b ) на самом деле адрес первого элемента массива b[ 5 ] bPtr = &b[ 0 ] Явно присваиваем bPtr адрес первого элемента b Явно присваиваем bPtr адрес первого элемента b

7.8Связь между указателями и массивами Элемент b[ 3 ] Элемент b[ 3 ] Может быть получен как *( bPtr + 3 ) Может быть получен как *( bPtr + 3 ) Нотация вызова указатель/смещение Нотация вызова указатель/смещение Может быть получен как bptr[ 3 ] Может быть получен как bptr[ 3 ] Нотация вызова указатель/индекс Нотация вызова указатель/индекс bPtr[ 3 ] это то же самое что и b[ 3 ] bPtr[ 3 ] это то же самое что и b[ 3 ] Может быть получен как выполнение арифметической операции над самим массивом Может быть получен как выполнение арифметической операции над самим массивом *( b + 3 )

7.9Массивы указателей Массивы могут содержать указатели Массивы могут содержать указатели Например: массив строк Например: массив строк char *suit[ 4 ] = { "Hearts", "Diamonds", "Clubs", "Spades" }; Строки это указатели на первый символ Строки это указатели на первый символ char * – каждый элемент suit это указатель на char char * – каждый элемент suit это указатель на char Строки на самом деле не хранятся в массиве suit, там хранятся только указатели на строки Строки на самом деле не хранятся в массиве suit, там хранятся только указатели на строки массив suit имеет фиксированный размер, но строки могут быть любого размера массив suit имеет фиксированный размер, но строки могут быть любого размера suit[3] suit[2] suit[1] suit[0]Hearts \0 Diamonds Clubs Spades

7.10 Пример: смешать колоду карт и раздать карты Программа перемешивания карт Программа перемешивания карт Use array of pointers to strings Use array of pointers to strings Use double scripted array (suit, face) Use double scripted array (suit, face) The numbers 1-52 go into the array The numbers 1-52 go into the array Representing the order in which the cards are dealt Representing the order in which the cards are dealt deck[ 2 ][ 12 ] represents the King of Clubs Hearts Diamonds Clubs Spades AceTwoThreeFourFiveSixSevenEightNineTenJackQueenKing Clubs King

7.10 Пример: смешать колоду карт и раздать карты Псевдокод Псевдокод Верхний уровень: Верхний уровень: Перемешать и раздать 52 карты Первое приближение: Первое приближение: Инициализация массива suit Инициализация массива face Инициализация массива deck Перемешать deck Раздать 52 карты

7.10 Пример: смешать колоду карт и раздать карты Второе приближение Второе приближение Преобразуем перемешать deck в Преобразуем перемешать deck в Для каждой из 52 карт Положить номер карты в случайно выбранное и незанятое в массиве deck Преобразуем раздать 52 карты в Преобразуем раздать 52 карты в Для каждой из 52 карт Найти номер карты в массиве deck и напечатать масть и ранг карты

7.10 Пример: смешать колоду карт и раздать карты Третье приближение Третье приближение Преобразуем перемешать deck в Преобразуем перемешать deck в Выберем случайно элемент deck Пока выбранный элемент deck не выбран Выберем масть deck случайно Пока выбранный элемент deck не выбран Выберем масть deck случайно Разместим выбранную карту в выбранный раздел deck Преобразуем раздать 52 карты в Преобразуем раздать 52 карты в Для каждого элемента в массиве deck Если слот содержит номер карты Печатает карту

1. Инициализируем массивы suit и face 1.1 Инициализируем массив deck 2. Вызовем функцию shuffle 2.1 Вызовем функцию deal 3. Определение функции 1/* Fig. 7.24: fig07_24.c 2 Card shuffling dealing program */ 3#include 4#include 5#include 6 7void shuffle( int [][ 13 ] ); 8void deal( const int [][ 13 ], const char *[], const char *[] ); 9 10int main() 11{ 12 const char *suit[ 4 ] = 13 { "Hearts", "Diamonds", "Clubs", "Spades" }; 14 const char *face[ 13 ] = 15 { "Ace", "Deuce", "Three", "Four", 16 "Five", "Six", "Seven", "Eight", 17 "Nine", "Ten", "Jack", "Queen", "King" }; 18 int deck[ 4 ][ 13 ] = { 0 }; srand( time( 0 ) ); shuffle( deck ); 23 deal( deck, face, suit ); return 0; 26} 27 28void shuffle( int wDeck[][ 13 ] ) 29{ 30 int row, column, card; for ( card = 1; card

3. Определение функции 33 do { 34 row = rand() % 4; 35 column = rand() % 13; 36 } while( wDeck[ row ][ column ] != 0 ); wDeck[ row ][ column ] = card; 39 } 40} 41 42void deal( const int wDeck[][ 13 ], const char *wFace[], 43 const char *wSuit[] ) 44{ 45 int card, row, column; for ( card = 1; card

Результат Six of Clubs Seven of Diamonds Ace of Spades Ace of Diamonds Ace of Hearts Queen of Diamonds Queen of Clubs Seven of Hearts Ten of Hearts Deuce of Clubs Ten of Spades Three of Spades Ten of Diamonds Four of Spades Four of Diamonds Ten of Clubs Six of Diamonds Six of Spades Eight of Hearts Three of Diamonds Nine of Hearts Three of Hearts Deuce of Spades Six of Hearts Five of Clubs Eight of Clubs Deuce of Diamonds Eight of Spades Five of Spades King of Clubs King of Diamonds Jack of Spades Deuce of Hearts Queen of Hearts Ace of Clubs King of Spades Three of Clubs King of Hearts Nine of Clubs Nine of Spades Four of Hearts Queen of Spades Eight of Diamonds Nine of Diamonds Jack of Diamonds Seven of Clubs Five of Hearts Five of Diamonds Four of Clubs Jack of Hearts Jack of Clubs Seven of Spades

7.11 Указатель на функции Указатель на функцию Указатель на функцию Содержит адрес функции Содержит адрес функции Похоже на то как имя массива содержит адрес первого элемента Похоже на то как имя массива содержит адрес первого элемента Имя функции адрес начала кода, который определяет функцию Имя функции адрес начала кода, который определяет функцию Указатели на функцию Указатели на функцию Передаются функции Передаются функции Сохраняются в массивах Сохраняются в массивах Присваиваются другим указателям на функцию Присваиваются другим указателям на функцию

7.11 Указатель на функции Пример: сортировка пузырьком Пример: сортировка пузырьком Функция bubble принимает указатель на функцию Функция bubble принимает указатель на функцию bubble вызывает эту функцию bubble вызывает эту функцию Определяет порядок сортировки Определяет порядок сортировки Аргумент в bubblesort – указатель на функцию: Аргумент в bubblesort – указатель на функцию: bool ( *compare )( int, int ) Говорит bubblesort ожидать указателя на функцию которая получает два int и возвращает один bool Если скобки убрать: Если скобки убрать: bool *compare( int, int ) Определяет функцию которая получает два integers и возвращает указатель на bool Определяет функцию которая получает два integers и возвращает указатель на bool

1. Инициализация массива 2. Запрос на тип сортировки 2.1 Разместим необходимый указатель на функцию в bubblesort 2.2 Вызовем bubble 3. Печатаем результаты 1/* Fig. 7.26: fig07_26.c 2 Multipurpose sorting program using function pointers */ 3#include 4#define SIZE 10 5void bubble( int [], const int, int (*)( int, int ) ); 6int ascending( int, int ); 7int descending( int, int ); 8 9int main() 10{ int order, 13 counter, 14 a[ SIZE ] = { 2, 6, 4, 8, 10, 12, 89, 68, 45, 37 }; printf( "Enter 1 to sort in ascending order,\n" 17 "Enter 2 to sort in descending order: " ); 18 scanf( "%d", &order ); 19 printf( "\nData items in original order\n" ); for ( counter = 0; counter < SIZE; counter++ ) 22 printf( "%5d", a[ counter ] ); if ( order == 1 ) { 25 bubble( a, SIZE, ascending ); 26 printf( "\nData items in ascending order\n" ); 27 } 28 else { 29 bubble( a, SIZE, descending ); 30 printf( "\nData items in descending order\n" ); 31 } 32 Параметр – указатель на функцию

3.1 Определим функции 33 for ( counter = 0; counter < SIZE; counter++ ) 34 printf( "%5d", a[ counter ] ); printf( "\n" ); return 0; 39} 40 41void bubble( int work[], const int size, 42 int (*compare)( int, int ) ) 43{ 44 int pass, count; void swap( int *, int * ); for ( pass = 1; pass < size; pass++ ) for ( count = 0; count < size - 1; count++ ) if ( (*compare)( work[ count ], work[ count + 1 ] ) ) 53 swap( &work[ count ], &work[ count + 1 ] ); 54} 55 56void swap( int *element1Ptr, int *element2Ptr ) 57{ 58 int temp; temp = *element1Ptr; 61 *element1Ptr = *element2Ptr; 62 *element2Ptr = temp; 63} 64 Ascending и descending возвращает true или false. bubble вызывает swap если функция вернула true. Указать на функцию вызывает функцию с помощью оператора разыменовывания. * не требуется, но отметим что compare это указатель на функцию а не функция

3.1 Определяем функцию Результат 65int ascending( int a, int b ) 66{ 67 return b < a; /* swap if b is less than a */ 68} 69 70int descending( int a, int b ) 71{ 72 return b > a; /* swap if b is greater than a */ 73} Enter 1 to sort in ascending order, Enter 2 to sort in descending order: 1 Data items in original order Data items in ascending order Enter 1 to sort in ascending order, Enter 2 to sort in descending order: 2 Data items in original order Data items in descending order