рефераты

рефераты

 
 
рефераты рефераты

Меню

Реферат: Turbo C++ Programer`s guide рефераты

int highval = 1024;

printf("highval=%d\n", highval);

4 Символ обратной наклонной черты для продолжения строки: длинная последовательность лексем может продлитьстрокупри помощи обратной наклонной черты (\). Символы обратной наклонной черты и новой строки оба вырезаются, и в результате образуется фактическая последовательность лексем, используемая в расширении:

#define WARN "фактически это одно\

строчное сообщение"

...

puts(WARN);

/* на экране будет: фактически это однострочное сообщение */

5. Побочные эффекты и прочие опасности: схожесть между вызовами макросов и функциями иногда скрывает различия между ними. При вызове макроса отсутствует встроенный контроль типов данных, поэтому различиев типах данных формального и фактического аргументов может вызвать непредсказуемые результаты, причину которых нелегко установить, причем относительно такой ошибки не будет выдано никаких предупреждений. При вызовах макросов могут также возникнуть нежелательные побочные эффекты, особенно когдафактический аргумент вычисляется более одного раза. Сравните CUBE и cube в следующем примере:

int cube(int x) (*

return x*x*x;

*)

#define CUBE(x) ((x)*(x)*(x))

...

int b =0, a = 3;

b = cube(a++);

/* cube() передается фактический аргумент = 3; поэтому b = 27, и теперь a = 4 */

a = 3;

b = CUBE(a++);

/* расширяется в:  ((a++)*(a++)*(a++)); и теперь a = 6 */

Итоговое значение b зависит от того, что компилятор делает с расширенным выражением.

Включение файлов директивой #include

Директива #include подключает к исходному коду заданные в ней файлы, известные как включаемые файлы, файлы заголовковили заголовки. Синтаксис этой директивы имеет три формы:

#include <имя_заголовка>

#include "имя_заголовка"

#include идентификатор_макроса

В данном случае угловые скобки являются фактически записываемымив тексте директивы лексемами, а не метасимволами, обозначающими, что имя_заголовка является опциональным.

Третий вариант записи предполагает, что ни символ <, ни символ " не являются первым не-пробельным символом, следующим за #include; кроме того, предполагается, что существует такое макроопределение, которое расширит идентификатор макроса в допустимое, следующее за разделителем имя заголовка в формате либо <имя_заголовка>, либо "имя_заголовка".

Первый и второй варианты предполагают, что попыток макрорасширений сделано не будет; другими словами, имя_заголовка никогда не сканируется в поискахидентификаторов макросов. Имя_заголовка должно быть допустимым именем файла DOS с расширением (традиционно файлы заголовка имеют расширение .h) и опциональнымименемпути доступа к немус соответствующими разделителями.

Препроцессор удаляет строку #include и заменяет ее, начиная с текущей строки исходного кода, полным текстом файла заголовка. Сам исходный код остается без изменений,однакокомпилятор "видит" весь расширенный текст целиком. Таким образом, помещение в текст директивы #include может повлиять на контекст и продолжительность жизни любых идентификаторов во включаемых файлах.

Если поместить в имя_заголовка полное имя пути доступа к файлу, то поиск файла будет выполнентольков указанной таким образом директории.

Различиемежду форматами <имя_заголовка> и "имя_заголовка" заключается в алгоритме поиска включаемого файла, применяемом в каждом случае; эти алгоритмы описаны в следующих двух разделах.

Поиск файла заголовка при формате <имя_заголовка>

Вариант <имя_заголовка>задает стандартный включаемый файл; поиск последовательно выполняется во всех включаемых директориях в той последовательности, в которой они определены. Если ни в одной из этих директорий по умолчанию искомый файл не найден, то выдается сообщение об ошибке.

Поиск файла заголовка при формате "имя_заголовка"

Вариант "имя_заголовка" задает включаемый файл, создаваемый пользователем; сначала выполняется его поиск в текущей директории (обычно в той директории, в которой находится исходный компилируемый файл). Если там файл не найден, то поиск продолжается во всех включаемых директориях, как в случае формата <имя_заголовка>.

Приводимые ниже примеры поясняют описанные различия:

#include <stdio.h>

/* заголовок из стандартной включаемой директории */

#define  myinclude"c:\tc\include\mystuff.h"

/* Примечание: здесь допустимы одинарные символы обратной

наклонной черты; в операторе С пишется:

"c:\\tc\\include\\mystuff.h"  */

#include myinclude

/* макрорасширение */

#include "myinclude.h"

/* макрорасширение отсутствует */

После расширения второй оператор#include заставит препроцессор искать нужный файл в C:\TC\INCLUDE\mystuff.h, и нигде более. Третий пример #includeзаставляет препроцессор выполнить поискmyinclude.h сначала в текущей директории, а затем во включаемых директориях.

Условная компиляция

Turbo C++ поддерживаетусловную компиляцию путем замены соответствующих строк исходного кода пустой строкой. Игнорируемые таким образом строки это те строки, что начинаются с символа # (за исключением директив #if, #ifdef, #ifndef, #else, #elif и #endif), а также любые строки, которые в результате выполнения директив не должны компилироваться. Все директивы условной компиляции должны завершаться в том же исходном или включаемом файле, где находится их начало.

Директивы условной компиляции #if, #elif, #else и #endif

Директивы условной компиляции #if, #elif, #else и #endif работают аналогично обыкновенным условным операторам

С.Они используются следующим образом:

#if выражение-1-типа-константы

<раздел-1>

<#elif выражение-2-типа-константы новая-строка раздел-2>

...

<#elif выражение-n-типа-константы новая-строка раздел-n>

<#else последний-раздел>

#endif

...

Если выражение-1-типа-константы(для котороговыполняется макрорасширение) дает ненулевое значение (истина), то строки кода (возможно, пустые), представленногоразделом-1, которые могут представлять собой как командные строки препроцессора, так и обычные строки исходного кода, обрабатываются препроцессором и соответствующим образом передаются компилятору Turbo C++. В противном случае, если выражение-1-типа-константы дает нулевое значение (ложь), раздел-1игнорируется (макрорасширение и компиляция данного раздела не выполняются).

В случае "истина" после обработки раздела-1 препроцессором управление передается соответствующейдирективе #endif (которая заканчивает даннуюусловную конструкцию) и продолжается в следующем-разделе. В случае "ложь" управление передается следующей строке #elif (если она определена в данной конструкции),где вычисляетсявыражение-2-типа-константы. В случае "истины" обрабатывается раздел-2, после чего управление передается соответствующей директиве #endif, и т.д.,до тех пор, пока не будет достигнута последняя директива #else или #endif. Опциональная директива #else используется в качестве альтернативного условия в том случае, если все предыдущие проверки дали значение "ложь". Последовательность условных директив заканчивается директивой #endif.

Обработанный препроцессором раздел может в свою очередь содержать вложенные на любую глубину условные предложения, причем каждой директиве #if должна соответствовать закрывающая директива #endif.

Итоговым результатом вышеописанного сценария является то, что для дальнейшей обработки передается только один раздел (возможно, пустой). Опущенныеразделы служат только для отслеживания возможных вложенных условных конструкций, так что каждая директива #if должна обязательно иметь соответствующую ейзавершающую директиву #endif.

Проверяемые выражения-типа-константы при вычислении должны давать целочисленную константу.

Операция defined

Операция defined дает альтернативный, более гибкий способ проверки того, определены ли комбинации идентификаторов, или нет. Данная операция допустима только в выражениях #if и #elif.

Выражение defined(идентификатор)или defined идентификатор (скобки необязательны) дает 1 (истина), если данное символическое имя было ранее определено (при помощи директивы # defined) иэто определение не было впоследствии отменено (при помощи #undef); в противном случае оно дает 0 (истина). Поэтому директива

#if defined(mysym)

это то же, что

#ifdef mysym

Преимущество заключается в том, что можно использовать defined циклически в сложном выражении, следующем за директивой #if, например

#if defined(mysym) && !defined(yoursym)

Условные директивы #ifdef и #ifndef

Условные директивы #ifdef и #ifndef позволяют проверить, определен лив текущий момент данный идентификатор, то есть была ли обработана предыдущаядиректива #define для данного идентификатора и продолжает ли она действовать в текущий момент.

Строка

#ifdef идентификатор

имеет точно такой же эффект, что и

#if 1

если идентификатор в текущий момент определен, и такой же эффект, что и

#if 0

если идентификатор в текущий момент не определен.

#ifndef, напротив, дает значение "истина", если идентификатор "не определен", поэтому строка

#ifndef идентификатор

имеет точно такой же эффект, что и

#if 0

если идентификатор в текущий момент определен, и такой же эффект, что и

#if 1

если идентификатор в текущий момент не определен.

Синтаксис следует синтаксису директив #if, #elif, #else и #endif, описанному в предыдущем разделе.

Идентификатор, определенный как имеющий пустое (NULL) значение, считается определенным.

Директива управления нумерацией строк #line

Директива #lineслужитдля заданияпрограмме способа нумерации строк, используемой при создании перекрестных ссылок и при выдаче сообщений об ошибках. Если программасостоит из разделов, взятых из других программных файлов, часто бывает полезно обозначить такиеразделы номерами строк, взятыми из соответствующего исходного текста, а не обычными последовательными номерами строк составной программы. Синтаксис директивы следующий:

#line целочисленная-константа <"имя-файла">

и обозначает, что следующая исходная строка берется начиная с номера строки, заданного целочисленной-константой, из файла, заданного "именем-файла". После того, как имя-файла было однажды задано, все последующие команды #line, относящиеся к данному файлу, может опустить явный аргумент имя-файла. Например,

/* TEMP.C: пример директивы #line  */

#include <stdio.h>

#line 4 "junk.c"

void main()

(*

printf(" in line %d of %s",__LINE__,__FILE__);

#line 12 "temp.c"

printf("\n");

printf(" in line %d of %s",__LINE__,__FILE__);

#line 8

printf("\n");

printf(" in line %d of %s",__LINE__,__FILE__);

*)

Включение stdio.h означает, что на выходе препроцессора будет нечто большее.

Если запустить TEMP.C через CPP (cpp temp), то на выходе получится файл TEMP.I, который выглядит так:

temp.c 1:

c:\borland\tc\cpp\include\stdio.h 1:

c:\borland\tc\cpp\include\stdio.h 2:

c:\borland\tc\cpp\include\stdio.h 3:

...

c:\borland\tc\cpp\include\stdio.h 212:

c:\borland\tc\cpp\include\stdio.h 213:

temp.c      2:

temp.c      3:

junk.c       4: void main()

junk.c       5: (*

junk.c       6: printf(" in line %d of %s",6,"junk.c");

junk.c       7:

temp.c      12: printf("\n");

temp.c      13: printf(" in line %d of %s",13,"temp.c");

temp.c      14:

temp.c      8: printf("\n");

temp.c      9: printf(" in line %d of %s",9,"temp.c");

temp.c      10: *)

temp.c      11:

Если вызатем компилируете TEMP.C, то получится следующий выход:

in line 6 of junk.c

in line 13 of temp.c

in line 9 of temp.c

Макросы расширяются в аргументах #line, как в директивах #include.

Прежде всего назначение директивы #line заключается в использовании ее в утилитах, имеющих на выходе коды С, а не в кодах, создаваемых человеком "вручную".

Директива #error

Директива #error имеет следующий синтаксис:

#error сообщение-об-ошибке

Директива генерирует сообщение:

Error: имя-файла номер-строки : Error directive: сообщение

Данная директива обычно встраивается в условные конструкции препроцессора, которые отслеживают какие-либо нежелательные условия времени компиляции.Обычноэто условие "ложно". Если условие "истинно", то компилятор может выдать сообщение об ошибке и прекратитьработу. Для этого директива# error помещается в условную ветвь, которая дает для искомого нежелательного условия результат "истина".

Например, вы определили #define MYVAL, принимающую значения 0 или 1. Затем можновключить в исходный код условную директиву, которая будет проверять MYVAL на предмет неверного значения:

#if (MYVAL != 0 && MYVAL != 1)

#error MYVAL must be defined to either 0 or 1

#endif

Директива #pragma

Директива #pragma позволяет использовать специфичные для конкретных реализаций директивы в форме

#pragma имя-директивы

При помощи #pragma Turbo C++позволяет определить любые желаемые директивы, не обращаясь дляэтогок другим, поддерживающим их компиляторам. Если компилятор не поддерживает данное имя-директивы, то он просто игнорируетдирективу #pragma, не выдаваяпри этом никаких сообщений об ошибкахили предупреждений.

Turbo C++ поддерживает следующие директивы #pragma:

- #pragma argsused

- #pragma exit

- #pragma inline

- #pragma option

- #pragma saveregs

- #pragma startup

- #pragma warn

Директива #pragma argsused

Директива #pragma argsused допустима только между определениями функций и действует только на следующую функцию. Она отменяет сообщение уровня предупреждения:

"Parameter name is never used in function имя-функции" ("имя параметра нигде не используется в функции имя-функции")

Директивы #pragma exit и #pagma startup

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

Синтаксис этих директив следующий:

#pragma exit имя-функции <приоритет>

#pragma startup имя-функции <приоритет>

Заданное имя-функции должно относиться к ранееобъявленной функции, не принимающей аргументов и возвращающей значение void; другими словами, эта функция должна быть объявлена как:

void func(void);

Опциональный параметр приоритет должен являться целым числом в диапазоне от 64 до 255. Старшим приоритетом является 0. (Приоритеты от 0 до 63 используются библиотеками С и не должны использоваться пользователем). Функции со старшими приоритетами вызываются первыми при загрузке программы и последними при выходе из нее. Если приоритет не задан, то по умолчанию он равен 100. Например,

#include <stdio.h>

void startFunc(void)

(*

printf("Startup function.\n");

*)

#pragma startup startFunc 64

/* приоритет 64 --> вызывается при загрузке первой */

void exitFunc(void)

(*

printf("Wrapping up execution.\n");

*)

#pragma exit exitFunc

/* приоритет по умолчанию равен 100 */

void main(void)

(*

printf(This is main.\n");

*)

Отметим, что имя функции, используемой в #pragma startupили exit, должно быть определено (или объявлено) до того,как встретится соответствующая строка с директивой #pragma.

Директива #pragma inline

Данная директиваэквивалентна опции компилятора командной строки -B или соответствующей опции интегрированной среды Turbo. Она сообщаеткомпилятору, что программа содержит встроенные ассемблерные коды (см. главу 6, "Интерфейс с языком ассемблера"). Синтаксис ее следующий:

#pragma inline

Эту директиву лучше всего помещать вверху файла, поскольку, встретив директиву #pragma inline, компилятор перезапускает себя с опцией -B. Фактически можно опустить и опцию -В, и директиву #pragma inline, и компилятор тем не менее выполнитперезапуск, когда встретит операторы asm. Назначение опции и директивы состоит в том, чтобы сэкономить время компиляции.

Директива #pragma option

Директива #pragma option используетсядля включения опций компилятора командной строки в код вашей программы. Синтаксис этой директивы следующий:

#pragma option [опции...]

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

Ниже приводятсяопции,которые не могут находиться в директиве pragma option:

-B (компиляция с использованием ассемблерных кодов)

-c (компиляция без компоновки)

-dxxx (определение макроса)

-Dxxx = ccc (определение макроса с текстом)

-efff (имя .EXE-файла fff)

-lfff (имя включаемой директории)

-Lfff (имя директории с библиотекой)

-lxset (опция компоновщика x)

-M (создание при компоновке .MAP-файла)

-o оверлеи

-Q EMS

-S (создание на выходе .ASM-файла и остановка)

-Uxxx (отмена определения макроса)

-V (virtual)

-Y (оверлеи)

Существует два состояния компилятора. В первом состоянии в директиву pragma option можно включить большее количество опций, нежели во втором. Первое состояние компилятора называется состоянием лексического анализа,а второе - состоянием кодирования.

Использование имени макроса, начинающегося двумя символами подчеркивания (которое может являться именем встроенного макроса), в директивах #if, #ifdef, #ifndef или #elifизменяет состояние компилятора на состояние кодирования.

Появление первой реальной лексемы  (первого  объявления

С) также изменяет состояние компилятора на кодирование.

Другими словами, можноиспользовать директивы #pragma, # include, #define и некоторые разновидности #if во время состояния лексического анализакомпилятора. Во время этой фазы вы имеете возможность при помощи #pragma option изменять опции командной строки.

Страницы: 1, 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