- •Предисловие
- •Контрольные вопросы
- •Библиографический список
- •Тема 2 Переменные и базовые типы данных языка с
- •Контрольные вопросы
- •Библиографический список
- •Тема3 Организация циклов в языке с
- •Контрольные вопросы
- •Библиографический список
- •Тема 4 Принятие решений. Условные операторы в языке с
- •Контрольные вопросы
- •Библиографический список
- •Тема 5 Числовые массивы в языке программирования с
- •Тип имя_массива[размер];
- •Тип имя_массива[размер1] [размер2];
- •Тип имя_массива[размер1] [размер2] [размерN];
- •Контрольные вопросы
- •Библиографический список
- •Тема 6 Символьные массивы в языке с. Работа со строками
- •Тип имя_массива[размер];
- •Тип имя_массива[размер1] [размер2];
- •Тип имя_массива[размер1] [размер2] [размерN];
- •Контрольные вопросы
- •Библиографический список
- •Тема 7 Указатели в языке программирования с
- •Int *ptr; // объявили указатель на целую переменную
- •Контрольные вопросы
- •Библиографический список
- •Тема 8 Указатели и массивы в языке с
- •Int data[7]; // обычный массив
- •Int *pd[7]; // массив указателей
- •Контрольные вопросы
- •Библиографический список
- •Тема 9 Динамическое распределение памяти в языке с
- •If (!ptr) // условие логического отрицания
- •If (!ptr) // условие логического отрицания
- •Контрольные вопросы
- •Библиографический список
- •Тема 10 Функции Общие сведения о функциях языка с
- •Fun(тип имя_перем1, тип имя_перем2, , тип имя_перем n)
- •Контрольные вопросы
- •Библиографический список
- •Тема 11 Указатели и функции в языке программирования с
- •Тип_возвращаемый_функцией(*имя_указателя_на_функцию)(аргументы);
- •Контрольные вопросы
- •Библиографический список
- •Тема 12 Файловый ввод/вывод в языке с
- •Контрольные вопросы
- •Библиографический список
- •Тема 13 Структуры – производные типы данных языка с
- •Int age; // возраст
- •Int age; // возраст
- •Int age; // возраст
- •Int age; // возраст
- •Int age; // возраст
- •Int age; // возраст
- •Контрольные вопросы
- •Библиографический список
- •Тема 14 Объединения и перечислимые типы в языке с
- •Контрольные вопросы
- •Библиографический список
- •Тема 15 Структуры и функции языка с
- •Контрольные вопросы
- •Библиографический список
- •Тема 16 Операции с разрядами (битами) в языке с
- •Контрольные вопросы
- •Библиографический список
- •Тема 17 Программы, состоящие из нескольких файлов, на языке с
- •Спецификатор extern
- •Спецификатор static
- •Спецификатор register
- •Спецификатор auto
- •Контрольные вопросы
- •Библиографический список
- •Тема 18 Рекурсивные алгоритмы и функции
- •Переместить (a, b);
- •Контрольные вопросы
- •Библиографический список
- •Тема 19 Препроцессор языка с
- •Директива #define
- •Директива #error
- •Директива #include
- •Директивы условной компиляции
- •2_ Я_последовательность операторов программного кода
- •3_ Я_последовательность операторов программного кода
- •Директива #line
- •Директива #pragma
- •Предопределенные символические константы
- •Макрос подтверждения assert
- •Контрольные вопросы
- •Библиографический список
- •Тема 20 Программы на языке с при использовании статически подключаемой библиотеки
- •Контрольные вопросы
- •Библиографический список
- •Тема 21 Использование аргументов командной строки в с
- •Контрольные вопросы
- •Контрольная работа № 2 Покупки в супермаркете
- •Приложение Управление конфигурациями проекта в Visual Studio 2010
Контрольные вопросы
Что лежит в основе всех программ, созданных на языке С?
Какие типы данных функция возвращать может и что не может?
Что такое прототип функции? Какие элементы объявления функции входят в ее прототип?
В чем разница между фактическими и формальными параметрами функции?
Какой способ передачи параметров в функциях предусматривает синтаксис языка С?
Как можно изменить значение аргумента функции в теле самой функции?
Какова область видимости переменных, определенных в теле функции?
Можно ли использовать функцию без параметров и без служебного слова void? К каким последствиям это может привести?
Какие обязательные атрибуты должна содержать функция с переменным числом аргументов?
Библиографический список
Шилдт Г. Полный справочник по С : пер. с англ./Г. Шилдт. – 4-е изд. – М.: Вильямс, 2007. – 704 с.
Кочан С. Программирование на языке С : пер. с англ./С. Кочан. – 3-е изд.– М.: Вильямс, 2007. – 496 с.
Харбисон С. П. Язык программирования С : пер. с англ./С. П. Харбисон, Г. Л. Стил. – М. : Бином-Пресс, 2004. – 528 с.
Березин Б.И. Начальный курс С и С++/Б.И.Березин, С.Б.Березин. – М.: ДИАЛОГ-МИФИ, 1998. – 288 с.
Подбельский В.В. Программирование на языке Си: учеб. пособие/ В.В.Подбельский, С.С.Фомин. – 2-е изд., доп. – М.: Финансы и статистика, 2007. – 600 с.
Хусаинов Б.С. Структуры и алгоритмы обработки данных. Примеры на языке Си (+CD) : учеб. пособие / Б.С. Хусаинов. – М.: Финансы и статистика, 2004. – 464 с.
Тема 11 Указатели и функции в языке программирования с
Изучаются вопросы программирования функций, аргументами которых могут быть указатели, а также функции, возвращающие значения через указатели.
ТЕОРЕТИЧЕСКАЯ ЧАСТЬ
В предыдущей теме анализировались примеры функций, аргументами которых выступали указатели. Здесь подробнее будут рассмотрены вопросы, касающиеся указателей и функций.
Ранее было отмечено, что в языке С аргументы передаются в функции по значению и не существует прямого способа изменить переменную вызывающей функции, действуя внутри вызываемой функции. Благодаря аргументам-указателям функция может обращаться к объектам в вызвавшей ее функции, в том числе модифицировать их [1]. В качестве примера рассмотрим функцию swap(), в задачу которой входит обмен элементов местами. Для решения такой задачи необходимо передать из вызывающей программы (например, из главной функции main()) в функцию указатели на переменные, которые нужно изменить.
Программный код решения примера
#include <stdio.h> #include <conio.h>
// Прототип функции void swap(int*, int*);
int main (void) { int a = 10, b = -20; // Вывод на консоль исходных значений переменных printf("\n Initial values:\n a = %d, b = %d\n", a, b);
// Вызов функции swap() с фактическими параметрами swap(&a, &b);
// Результат после обращения функции swap() printf("\n New values:\n a = %d, b = %d\n", a, b);
printf("\n ... Press any key: "); _getch(); return 0; }
// Определение функции void swap(int *pa, int *pb) { int temp; temp = *pa; *pa = *pb; *pb = temp; }
|
В программе в качестве фактических параметров функции swap() выступают адреса заданных переменных. Можно было в главной функции определить указатели и инициализировать их адресами заданных переменных, а потом передать эти указатели в функцию swap.
Р езультат выполнения программы показан на рис.11.1.
Рис. 11.1. Результат обмена данными, выполненного функцией swap()
Указатели, передаваемые в функцию, могут ссылаться на указатели, обозначать начало какого-либо массива и т. д., использоваться для защиты массивов, над которыми необходимо произвести некоторые вычисления или преобразования. Особым свойством указателей можно считать возможность использования их в качестве возвращаемых значений функций. Поскольку функции возвращают только одно значение, то несколько значений одного типа можно поместить в массив, а затем указатель на этот массив использовать в качестве возвращаемого значения.
Общая форма определения функции, которая возвращает указатель, следующая:
тип *имя_функции ( аргументы функции )
{
// тело функции
тип *имя_указателя;
return имя_указателя;
}
Рассмотрим пример сложения двух одномерных массивов и результата возвращения через указатель.
Программный код решения примера
#include <stdio.h> #include <conio.h> #include <stdlib.h>
int *out2(int A[], int B[], int);
int main (void) { int i, n; int A[] = {1,2,3,4,5}; int B[] = {2,2,2,2,2}; int *ptrAB = NULL;
n = (sizeof(A)/sizeof(A[0]));
puts("\n The initial arrays: "); for (i = 0; i < n; i++) printf(" %d", A[i]);
puts(""); for (i = 0; i < n; i++) printf(" %d", B[i]);
ptrAB = out2(A, B, n); puts("\n\n Result from function: "); for (i = 0; i < n; i++) printf(" %d", ptrAB[i]);
puts("\n\n Control of the arrays: "); for (i = 0; i < n; i++) printf(" %d", A[i]);
puts(""); for (i = 0; i < n; i++) printf(" %d", B[i]);
free(ptrAB); // освобождение выделенной памяти printf("\n\n ... Press any key: "); _getch(); return 0; }
int *out2(int A[], int B[], int n) { int i; int *ptr = (int *)calloc(n, sizeof(int)); //выделение памяти
for (i = 0; i < n; i++) ptr[i] = A[i] + B[i];
return ptr; } |
Программа не требует особых пояснений. Однако отметим, что никогда не следует возвращать адрес переменной, определенной в теле функции, так как переменные функции являются локальными, и существуют только во время работы функции.
Указатели возвращаются подобно значениям любых других типов данных. Чтобы вернуть указатель, функция должна объявить его тип в качестве типа возвращаемого значения. Таким образом, если функция возвращает указатель, то значение, используемое в ее инструкции return, также должно быть указателем. В частности, многие библиотечные функции, предназначенные для обработки строк, возвращают указатели на символы.
В языке С существует такой механизм, как указатель на функцию. Допустим, существует несколько функций для различных операций с данными. В этом случае оказывается удобным определить указатель на функцию и использовать его там, где требуется производить расчет для различных функций.
Указатель на функцию – это переменная, содержащая в памяти адрес, по которому расположена функция [2]. Имя функции – это адрес начала ее программного кода. Указатели на функции могут передаваться функциям в качестве аргументов, возвращаться функциями, сохраняться в массивах и присваиваться другим указателям на функции [2].
Типичное определение указателя на функцию следующее: