Турбо С: руководство пользователя. Часть 2

Турбо С: руководство пользователя. Часть 2 - Стр. 34

Печать PDF
Индекс материала
Турбо С: руководство пользователя. Часть 2
Стр. 2
Стр. 3
Стр. 4
Стр. 5
Стр. 6
Стр. 7
Стр. 8
Стр. 9
Стр. 10
Стр. 11
Стр. 12
Стр. 13
Стр. 14
Стр. 15
Стр. 16
Стр. 17
Стр. 18
Стр. 19
Стр. 20
Стр. 21
Стр. 22
Стр. 23
Стр. 24
Стр. 25
Стр. 26
Стр. 27
Стр. 28
Стр. 29
Стр. 30
Стр. 31
Стр. 32
Стр. 33
Стр. 34
Стр. 35
Стр. 36
Стр. 37
Стр. 38
Стр. 39
Стр. 40
Стр. 41
Стр. 42
Стр. 43
Стр. 44
Стр. 45
Стр. 46
Стр. 47
Стр. 48
Стр. 49
Стр. 50
Стр. 51
Стр. 52
Стр. 53
Стр. 54
Стр. 55
Стр. 56
Все страницы
     тов, как,  например, функция printf. По этой причине вы не можете          
     использовать  эллипсис   (...)   (т.е.  опускать  подразумеваемый          
     параметр)  в  определении функции  типа  pascal.  (См. "Прототипы          
     функций"  для понимания  использования  элипсиса  при определении          
     функции с различным числом аргументов.)                                    
                                                                                
                                                                                
                                                                                
          Модификатор функции cdecl                                             
          -------------------------                                             
                                                                                
          Модификатор cdecl также является специфичным для  Турбо  Си.          
     Как и модификатор pascal,  он используется с функциями или указа-          
     телями на функции. Его действие отменяет директиву компилятора -p          
     и разрешает   вызывать функции как обычные функции Си.  Например,          
     если вы при компиляции вышеприведенной программы установили опцию          
     -p, но  захотели использовать printf, то должны поступить следую-          
     щим образом:                                                               
                                                                                
          extern cdecl printf();                                                
          putnums(int i, int j, int k);                                         

                         - 277,278 -
                                                                                
                                                                                
          cdecl main()                                                          
          {                                                                     
              putnums(1,4,9);                                                   
          }                                                                     
                                                                                
          putnums(int i, int j, int k)                                          
          {                                                                     
              printf("And the answers are: %d, %d и %d\n",i,j,k);               
          }                                                                     
                                                                                
          Если программа  компилируется  с опцией -p,  то все функции,          
     используемые из библиотеки времени выполнения,  необходимо объяв-          
     лять как   cdecl.  Если вы посмотрите файлы заголовков (такие как          
     STDIO.H), то  увидете, что каждая функция явно описана как cdecl,          
     т.е. заранее подготовлена к этому. Заметьте, что главная програм-          
     ма main должна быть также объявлена как cdecl, поскольку действие          
     стартового кода программы, написанного на Си, всегда начинается c          
     вызова модуля main.                                                        
                                                                                
                                                                                
                                                                                
                                                                                
          Модификатор функции interrupt                                         
          -----------------------------                                         
                                                                                
          Модификатор interrupt также является специфическим для Турбо          
     Си. Функции interrupt специально введены для использования с век-          
     торами прерываний процессоров типа 8086/8088. Турбо Си будет ком-          
     пилировать функцию типа interrupt в дополнительную функцию,  вход          
     и выход которой сохраняется в регистрах AX,  BX,  CX, DX, SI, DI,          
     ES и DS.  Другие регистры:  BP,  SP,  SS, CS и IP сохраняются как          
     часть последовательности  Си вызова или как часть самой обработки          
     прерывания. Рассмотрим  пример типичного определения функции типа          
     interrupt.                                                                 
                                                                                
          void interrupt myhandler()                                            
          {                                                                     
               . . .                                                            
          }                                                                     
                                                                                
          Вы можете объявлять  функции  прерываний  как  функции  типа          
     void. Функции прерываний могут объявляться для любой модели памя-          
     ти. Для всех моделей, исключая huge, в регистр DS заносится прог-          
     раммный сегмент данных.  Для модели huge в DS заносится модульный          

                         - 279,280 -
                                                                                
     сегмент данных.                                                            
                                                                                
                                                                                
          Модификаторы функций near, far и huge                                 
          -------------------------------------                                 
                                                                                
          Модификаторы  near, far, и huge специфичны для Турбо Си. Они          
     могут комбинироваться с модификаторами cdecl или pascal, но не  с          
     interrupt.  Не-interrupt  функции  могут быть объявлены как near,          
     far, или huge. Они по умолчанию устанавливаются для данной модели          
     памяти. Near-функции используют near-вызовы, а far- или huge-фун-          
     кции используют far-вызовы инструкций.  В  моделях  памяти  tiny,          
     small,  и  compact  специально неоговоренные функции по умолчанию          
     имеют тип near. В моделях medium и large неоговоренные функции по          
     умолчанию имеют тип far. В модели памяти huge  по  умолчанию  ис-          
     пользуется тип huge. Функции типа huge и far одинаковы за тем ис-          
     ключением  что  в регистр DS заноситься адрес сегмента данных ис-          
     ходного модуля когда вызывается huge-функция  и  он  сбрасывается          
     для far-функции. Функции типа huge обычно используются когда неб-          
     ходимо организовать интерфейс с кодом на языке ассемблера который          
     не может использовать некоторую память занятую из Турбо Си.                
                                                                                
                                                                                
                                                                                
                                                                                

          Прототипы функций (K&R 10.1.2)                                        
          ------------------------------                                        
                                                                                
          При объявлении функций в K&R допускается  только указание ее          
     имени,  типа и скобок без параметров.  Параметры  (если они есть)          
     объявляются только во время явного определения самой функции.              
                                                                                
          ANSI стандарт и Турбо Си  разрешают  использовать  прототипы          
     функций для объявления функции.  Эти объявления включают информа-          
     цию о параметрах функции. Компилятор использует данную информацию          
     для проверки вызовов функций на соответствие данных,  а также для          
     преобразования аргументов к требуемому типу. Рассмотрим следующий          
     фрагмент программы:                                                        
                                                                                
          long lmax(long v1, long v2);                                          
                                                                                
          main()                                                                
          {                                                                     
                int limit = 32;                                                 
                char ch   = 'A';                                                

                         - 281,282 -
                                                                                
                long mval;                                                      
                                                                                
                mval = lmax(limit,ch);                                          
          }                                                                     
                                                                                
          Используя прототип  функции  для  lmax,  эта программа будет          
     преобразовывать параметры limit и ch к типу long, используя стан-          
     дартные правила  преобразования,  прежде чем они будут помещены в          
     стек для обращения к lmax. При отсутствии прототипа функции пара-          
     метры limit и ch были бы помещены в стек, соответственно, как це-          
     лое значение и символ; в этом случае в lmax передавались бы пара-          
     метры, не  совпадающие по размеру и содержанию с ожидаемыми.  Это          
     ведет к возникновению проблем.  В то время как Си в K&R не выпол-          
     няет никакого контроля типа параметров или их числа,  использова-          
     ние прототипов   функций очень помогает выявлять "жучки" и другие          
     ошибки программистов.                                                      
                                                                                
          Прототипы функций  также помогают при документировании прог-          
     рамм. Например,   функция strcpy имеет два  параметра:   исходную          
     строку и  выходную строку.  Вопрос - как их распознать?  Прототип          
     функции                                                                    
                                                                                
                                                                                
          char  *strcpy(char *dest, char *source);                              
                                                                                
     делает это ясным.  Если в файле заголовка имеются прототипы функ-          
     ций, то вы можете распечатать этот файл и получить большую инфор-          
     мацию необходимую для написания программы,  вызывающей эти  функ-          
     ции.                                                                       
                                                                                
          Описание функции с включенным  в  скобки единственным словом          
     void означает, что функция совсем не имеет аргументов                      
                                                                                
             f(void)                                                            
                                                                                
          В противном случае, в скобках указывается список параметров,          
     разделенных запятыми. Так, объявление может быть сделано в виде:           
                                                                                
            func(int *, long);                                                  
                                                                                
     или с включением идентификаторов, как ниже:                                
                                                                                
                                                                                
            func(int *count, long total);                                       
                                                                                

                         - 283,284 -
                                                                                
          В обоих случаях,  указанных выше, функция func принимает два          
     параметра: указатель  на тип int,  названный count, и целую пере-          
     менную типа long,  названную total.  Включение  идентификатора  в          
     объявление имеет  смысл лишь для вывода его в диагностическом со-          
     общении, в случае возникновения несоответствия типа параметров.            
                                                                                
          Прототип обычно определяет функцию как функцию,  принимающую          
     фиксированное число параметров.  Для Си функций, принимающих раз-          
     личное число параметров (таких, как printf), пропотип функции мо-          
     жет заканчиваться элипсисом (...), например                                
                                                                                
          f(int *count, long total,...)                                         
                                                                                
          У прототипов такого вида фиксированные параметры проверяются          
     во время компиляции,  а опущенные передаются,  как при отсутствии          
     прототипа.                                                                 
                                                                                
          Рассмотрим несколько  примеров объявления функций и прототи-          
     пов.                                                                       
                                                                                
          int f();        /* Функция возвращает величину типа int без           
                            информации о параметрах. Это классический           
                                                                                
                                                         стиль K&R */           
                                                                                
          int f(void);    /* Функция возвращает значение типа int, */           
                                        /* параметры не передаются */           
                                                                                
          int p(int,long); /* Функция возвращает целое, а получает */           
                                                 /* два параметра; */           
                            /* первый имеет тип int, второй - long */