Типизированные и нетипизированные указатели

Рассмотренные указатели являются типизированными, т.е. могут указывать только на заданный тип данных.

Существуют также нетипизированные указатели (void*), способные указывать на любой тип данных. Сохранение размера и типа данного возложено на программиста.

Пример:

int x;

float y;

void *t = &x; //допустимо

*t = 5; // операция НЕДОПУСТИМА, т.к. неизвестен тип данного

*(int *)t = 5; //допустимо обращение при соответствующем приведении типов

t =& y;

*(double*)t = 2.5;

Для типизированных указателей определены операции сложения с числом и вычитания из них числа, при этом результатом является указатель того же типа, смещенный в памяти на заданное количество данных (т.е. на размер данного, умноженного на заданное смещение).

Также для типизированных указателей определена операция разности указателей. Данная операция возвращает количество элементов (размер_области_памяти/размер_элемента) между указателями.

Массивы

Массивы являются набором однотипных данных, последовательно размещённых в памяти.

Одномерный массив можно объявить так:

тип_данного имя_массива[размер];

Например: int x[5];

Обращение к элементам массива происходит через операцию []. Минимальный индекс всегда ноль. Максимальный индекс – на единицу меньше размера массива.

ВНИМАНИЕ Автоматический контроль границ отсутствует.

Имя массива является указателем на начало массива. Операция x[i] тождественно равна *(x+i).

Возможно использование многомерных массивов.

int x[4][4][3];

x[0][0][0] = 5;

Массивы могут инициализироваться значениями в фигурных скобках, при этом допустимо не указывать последнюю (самую левую) размерность. Если заданная размерность меньше инициализирующих аргументов, часть элементов останется неопределенна. Обратная ситуация вызовет ошибку.

Примеры:

int x[3][2]={{1,2},{3,4},{5,6}}; //заданы и размеры массива, и инициализирующие значения

long y[] = {1,2,3,4}; // размер массива определяется фактическому по количеству значений (4)

char t[][4] = {{1,2,3,4},{5,6}}; // последняя размерность определяется по числу значений (2) и // элементы t[1][2] и t[1][3] не определены

Функции работы с памятью

(заголовочные файлы alloc.h, stdlib.h, mem.h)

void* malloc(unsigned s) – выделение памяти s байт.

void* calloc(unsigned n, unsigned m) – выделение n элементов по m байт.

void* realloc(void* ptr, unsigned ns) – перевыделение памяти.

void free(void* ptr) – освобождение памяти.

int memcmp(void* s1, void* s2, unsigned n) – сравнивает две области памяти.

void* memcpy(const void* dest, const void* src, unsigned n) – копирование области памяти n байт из src в dest.

void* memset(void *ptr, int c, unsigned n) – запись числа c в память начиная с ptr.

Консольные функции.

void clreol() – удаление символов от курсора до конца строки.

void clrscr() – очистка экрана.

int cprintf(char *format [,..,]) – вывод строки с учётом параметров консоли.

void gotoxy(int x, int y) – перемещение курсора в позицию (x,y) экрана.

void textbackground(int c) – цвет фона.

void textcolor(int c) – цвет шрифта.

void textmode(int m) – режим (C40, C80, C4350).

Строки.

Строкой является массив данных типа char. Используется строка с завершающим нулём, то есть признаком конца строки является символ с кодом «0».

Строки могут инициализироваться текстом, заключенным в двойные кавычки: строковой константой, – которая имеет тип const char*.

char t[] = “Hello, World”;

Функции работы со строками (библиотека string.h).

char *strcat(char *dest, char *src) – в dest помещается результат объединения dest и src, возвращает ссылку на dest (!!! в dest должно быть достаточно места для помещения результата)

char *strchr(char *str, int c) – поиск символа «c» в str, результат – ссылка на первый найденный символ или NULL, если символ не найден;

int strcmp(char *str1, char *str2) – посимвольное сравнение строк, возвращает -1, если str1<str2, +1 если str1>str2 и 0 если str1==str2;

char* strcpy(char *dest, char *src) – копирует src в dest, возвращает указатель на dest;

unsigned strlen(char *str)

char* strset(char *str, int c) , возвращает s.

char *strstr(const char *str, const char *substr)

Определены модификации некоторых функций, принимающие в качестве дополнительного аргумента длину строки. Данные функции начинаются с strn вместо str. Это функции strncat, strncmp, strncpy, strnset.

Пример:

char* strncat(char *dest, char *src, unsigned n) – то же, что strcat, но используются n символов src.

Указатель на функции

Указатель на функцию используется для передачи точки входа в функцию другой функции в качестве аргумента.

тип_функции (*имя_указателя) (спецификация параметров)

пример:

void qsort(void *base, size_t nelem, size_t width, int (*fcmp)(const void *p1, const void *p2);

вызов: fcmp(p1,p2);

функция сравнения чисел:

int comp(const void *p1, const void *p2)

{

return *(int*)p1 - *(int*)p2;

}

Работа с файлами.

Для взаимодействия с файлами предназначена структура данных FILE. Данная структура хранит служебную информацию об открытых файлах, такую как права доступа, указатель на файловый буфер, положение курсора в файле и т.д.

Для работы с файлом его необходимо открыть, для этого предназначена функция

FILE *fopen(const char *filename,const char *mode);

filename – абсолютное или относительное имя файла, mode – режим открытия и доступа.

Режимы:

"r" – открытие существующего файла только для чтения (файл должен существовать);

"w" – создание пустого файла для записи;

"a" – открытие существующего файла для записи данных в конец файла; создание файла, если файла с заданным именем не существует;

"r+" – открытие существующего файла для чтения и записи (файл должен существовать);

"w+" – создание нового файла для чтения и записи;

"a+" – тоже, что “a”, но с возможностью чтения;

Другие функции работы с файлами:

int fclose( FILE *stream ); // 0 в случае успеха

int _fcloseall( void ); //количество закрытых файлов

int fflush(FILE *stream);

int feof( FILE *stream);

int fgetc( FILE *stream);

int fgetpos( FILE *stream, fpos_t *pos);

int fputc(int c, FILE *stream);

int fseek( FILE *stream, long offset, int origin);

long ftell( FILE *stream);

Существуют стандартные файлы (потоки) (тип данных – FILE*):

stdin – стандартный поток ввода (по умолчанию – клавиатура);

stdout – стандартный поток вывода (по умолчанию – монитор в текстовом режиме);

stderr – стандартный поток ошибок;

stdaux – стандартный вспомогательный поток;

stdprn – стандартный принтер.

Данные потоки могут быть переопределены с использованием функции fopen.

Форматированный ввод-вывод

Для форматированного вывода в поток предназначена функция

fprintf(FILE* stream, const char* formatted_string, arguments, …)

Для подстановки значений переменных в строку вывода используют символы подстановки (спецификаторы формата), начинающиеся с символа «%»:

%[флаги][размер][.точность][модификатор_длины]тип_данного[1]

Флаги:

«-» – выравнивание результата по левому краю (по умолчанию – по правому относительно заданного количества выводимых символов);

«+» – результат всегда начинается со знака (+/-);

«#» – особая форма отображения результата.

Размер показывает сколько символов отводится для записи результата, может быть представлен в следующих форматах:

n – минимум n символов отводится для записи числа, недостающие символы заменяются пробелами;

0n – то же, но недостающие символы заменяются нулями;

* – список аргументов содержит размеры данных.

Точность показывает для вещественных символов количество знаков после десятичной точки.

Модификатор длины может принимать одно из значений:

F – «длинный» указатель;

N – «короткий» указатель;

h – short int;

l – long int, double;

L – long double.

Тип данного может принимать одно из значений:

%d, %i – знаковое десятичное целое;

%u – беззнаковое десятичное целое;

%o – беззнаковое восьмеричное целое;

%x, %X – беззнаковое шестнадцатеричное целое;

%f – знаковое вещественное;

%e, %E – знаковое вещественное в экспоненциальной форме;

%g, %G – знаковое вещественное, форма зависит от числа, размера и точности;

%c – символ;

%s – строка;

%% – символ «%»;

%n, %p – указатель.

Аргументы, передаваемые в функцию, должны соответствовать количеству и типу спецификаторам формата.

Для форматированного ввода данных из потока используется функция

fscanf(FILE* stream, const char* formatted_string, arguments, …)

Строка также может содержать спецификаторы формата, при этом:

– при невозможности предобразования строки в число, число принимает значение ноль;

– строкой считается слово до разделителя (пробел, табуляция, перевод строки).

Для стандартных потоков определены аналогичные функции:

printf(const char* formatted_string, arguments, …)

scanf(const char* formatted_string, arguments, …)

являющиеся аналогами описанных ранее функций, разница заключается в том, что используются стандартные потоки ввода и вывода (stdin, stdout) которые в качестве аргументов не указываются.

Определены функции, использующие вместо потока строку:

sprintf(char *dest, const char* formatted_string, arguments, …)

sscanf(char *src, const char* formatted_string, arguments, …)

[1] Квадратные скобки не являются частью записи формата, а указывают на необязательность аргумента

Наши рекомендации