Препроцессор

Содержание

Директива препроцессора #IFDEF | #IFNDEF … #ENDIF

Выполняет условное включение группы команд в код на этапе компиляции, если определена константа этапа компиляции.

Синтаксис

#IFDEF | #IFNDEF ConstantName
	Commands

#ENDIF

Параметры#IFDEF Указывает, что на этапе компиляции следует включить заданную группу команд, если была определена константа этапа компиляции с именем ConstantName. Ниже описывается, каким образом группа команд включается в код на этапе компиляции при задании #IFDEF. Если константа ConstantName определена, на этапе компиляции включается группа команд, следующая за #IFDEF и предшествующая директиве #ELSE или #ENDIF (той из них, которая встретится раньше). Если константа ConstantName не определена и задана директива #ELSE, на этапе компиляции включается группа команд, следующая за #ELSE и предшествующая директиве #ENDIF. Если константа ConstantName не определена и директива #ELSE не задана, ни одна из команд, находящихся внутри структуры #IFDEF … #ENDIF, не включается на этапе компиляции.#IFNDEF Указывает, что на этапе компиляции следует включить заданную группу команд, если константа этапа компиляции с именем ConstantName не определена. Ниже описывается, каким образом группа команд включается в код на этапе компиляции при задании #IFNDEF. Если константа ConstantName не определена, на этапе компиляции включается группа команд, следующих за #IFNDEF и предшествующих директиве #ELSE или #ENDIF (той из них, которая встретится раньше). Если константа ConstantName определена и задана директива #ELSE, на этапе компиляции включается группа команд, следующих за #ELSE и предшествующих директиве #ENDIF. Если константа ConstantName определена и директива #ELSE не задана, ни одна из команд, находящихся внутри структуры #IFDEF … #ENDIF, не включается на этапе компиляции.ConstantName Задает константу этапа компиляции, существование которой определяет необходимость включения группы команд на этапе компиляции. Константы этапа компиляции определяются с помощью директивы #DEFINE.Commands Задают группу команд, включаемых на этапе компиляции.

Комментарии Структуру #IFDEF | #IFNDEF … #ENDIF можно вкладывать в другую структуру #IFDEF | #IFNDEF … #ENDIF. Комментарии можно располагать в одной строке с директивами #IFDEF, #IFNDEF, #ELSE и #ENDIF. Комментарии игнорируются во время компиляции и выполнения программы.

Пример


* В следующем примере создается константа этапа компиляции с именем
* MYDEFINE. Структура #IFDEF ... #ENDIF задает выдачу сообщения о том,
* была ли определена константа этапа компиляции.
#DEFINE MYDEFINE 1

#IFDEF MYDEFINE	
	WAIT WINDOW "MYDEFINE exists"
#ELSE
	WAIT WINDOW "MYDEFINE does not exist"
#ENDIF
Предыдущий Шаг | Следующий Шаг | ОглавлениеАвтор Каев Артем.

Область видимости директивы #define

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

#include <iostream> void boo() { #define MY_NAME «Alex» } int main() { std::cout << «My name is: » << MY_NAME; return 0; }

1 2 3 4 5 6 7 8 9 10 11 12 13

#include <iostream>

voidboo()

{ #define MY_NAME «Alex» }

intmain()

{

std::cout<<«My name is: «<<MY_NAME;

return;

}

Несмотря на то, что директива определена внутри функции boo(), препроцессор этого не заметит, так как он не понимает такие понятия C++, как функции. Следовательно, выполнение этой программы будет идентично той, в которой бы было определено ДО, либо сразу ПОСЛЕ функции boo(). Для лучше читабельности кода определяйте идентификаторы (с помощью #define) вне функций.

После того, как препроцессор завершит своё выполнение, все идентификаторы (определенные с помощью #define) из этого файла — отбрасываются. Это означает, что директивы действительны только с точки определения и до конца файла, в котором они определены. Директивы, определённые в одном файле кода, не влияют на директивы, определенные внутри других файлов этого же проекта.

Рассмотрим следующий пример:

function.cpp:

#include <iostream> void doSomething() { #ifdef PRINT std::cout << «Printing!»; #endif #ifndef PRINT std::cout << «Not printing!»; #endif }

1 2 3 4 5 6 7 8 9 10 11

#include <iostream>

voiddoSomething()

{ #ifdef PRINT

std::cout<<«Printing!»;

#endif #ifndef PRINT

std::cout<<«Not printing!»;

#endif }

main.cpp:

void doSomething(); // предварительное объявление функции doSomething() int main() { #define PRINT doSomething(); return 0; }

1 2 3 4 5 6 7 8 9 10

voiddoSomething();// предварительное объявление функции doSomething()

intmain()

{ #define PRINT

doSomething();

return;

}

Результат выполнения программы:

Несмотря на то, что мы объявили в main.cpp (), это всё равно не имеет никакого влияния на что-либо в function.cpp. Поэтому, при выполнении функции doSomething(), у нас выводится , так как в файле function.cpp мы не объявляли идентификатор (с помощью директивы #define). Это связано с header guards.

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

Директивы препроцессора условной компиляции позволяют определить, при каких условиях код будет компилироваться, а при каких — нет. На этом уроке мы рассмотрим только три директивы условной компиляции:

Директива #ifdef (англ. «if defined» = «если определено») позволяет препроцессору проверить, было ли значение ранее определено с помощью директивы #define. Если да, то код между #ifdef и #endif скомпилируется. Если нет, то код будет проигнорирован, например:

#define PRINT_JOE #ifdef PRINT_JOE std::cout << «Joe» << std::endl; #endif #ifdef PRINT_BOB std::cout << «Bob» << std::endl; #endif

1 2 3 4 5 6 7 8 9

#define PRINT_JOE

#ifdef PRINT_JOE

std::cout<<«Joe»<<std::endl;

#endif

#ifdef PRINT_BOB

std::cout<<«Bob»<<std::endl;

#endif


Поскольку уже был определен, то строка скомпилируется и выполнится. А поскольку не был определен, то строка не скомпилируется и, следовательно, не выполнится.

Директива #ifndef (англ. «if not defined» = «если не определено») — это полная противоположность к #ifdef, которая позволяет проверить, не было ли значение ранее определено. Например:

#ifndef PRINT_BOB std::cout << «Bob» << std::endl; #endif

1 2 3

#ifndef PRINT_BOB

std::cout<<«Bob»<<std::endl;

#endif

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

Общая структура применения директив условной компиляции

#if константное_выражение 1            Текст 1#elif константное_выражение 2            Текст 2#else            Текст 3#endif

Текст 1 включается в единицу трансляции, только если константное выражение истинноТекст 2, если константное выражение 2 истинно, а константное выражение 1 ложно

Если оба константных выражения ложны, то в единицу трансляции включается Текст 3

Если директива #else отсутствует, то текст не будет включаться в единицу трансляции в случае ложности всех константных выражений

#define VAR 1#if VAR == 1void f() {cout << “Var 1”;}#elif VAR == 2void f() {cout << “Var 1”;}#endifint main(){            f();}

Вместо директивы #if могут быть использованы директивы: #ifdef, #ifndef, которые проверяют, что препроцессорный идентификатор был определен или не был определен соответственно

#define I#ifdef Ivoid f() {…}void d() {…}#endif

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

Эти директивы удобно проверять для отладочной печати

#define DEBUG…#ifdef DEBUG…#endif

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

“myHeader.h”#ifndef MYHEADER            Определение классов, функций#define MYHEADER#endif

VS для защиты текстов от повторного включения применяет директиву #pragma once

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

Ограничение доступа к данным на уровне записей и полей

Среди действий над объектами, хранящимися в базе данных (справочниками, документами и т. д.), есть действия, отвечающие за чтение или изменение информации, хранящейся в базе данных. К таким действиям относятся:

  • чтение — получение записей или их фрагментов из таблицы базы данных;
  • добавление — добавление новых записей без изменения существующих;
  • изменение — изменение существующих записей;
  • удаление — удаление некоторых записей без внесения изменений в оставшиеся.

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

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

Ограничение доступа к данным представляет собой условие, описанное на языке, который является подмножеством языка запросов. Это условие применяется для каждой записи таблицы базы данных, над которой выполняется операция. Если условие принимает значение «истина», то операция выполняется, а если нет, то не выполняется. Условие ограничения доступа может быть уточнено с помощью инструкций препроцессора (#ЕСЛИ <условие>, #ТОГДА. и др.), что сделает его более эффективным. При просмотре списков и формировании отчетов существует возможность обеспечить отображение  только тех данных, доступ к которым пользователю разрешен.

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

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

Директива #define

Директива #define позволяет вводить в текст программы константы и макроопределения. Общая форма записи

#define Идентификатор Замена

ИдентификаторЗамена#defineЗаменаИдентификатор


12345678

#include <stdio.h>#define A 3int main(){  printf(«%d + %d = %d», A, A, A+A); // 3 + 3 = 6  getchar();  return 0;}

  • U или u представляет целую константу в беззнаковой форме (unsigned);
  • F (или f) позволяет описать вещественную константу типа float;
  • L (или l) позволяет выделить целой константе 8 байт (long int);
  • L (или l) позволяет описать вещественную константу типа long double

#define A 280U   // unsigned int#define B 280LU  // unsigned long int#define C 280    // int (long int)#define D 280L   // long int#define K 28.0   // double#define L 28.0F  // float#define M 28.0L  // long double

  идентификатор(аргумент1, …, агрументn)

заменаПример на Си

12345678910111213141516

#include <stdio.h>#include <stdlib.h>#include <math.h>#define PI 3.14159265#define SIN(x) sin(PI*x/180)int main(){  int c;  system(«chcp 1251»);  system(«cls»);  printf(«Введите угол в градусах: «);  scanf(«%d», &c);  printf(«sin(%d)=%lf», c, SIN(c));  getchar(); getchar();  return 0;}

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

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

12345678910111213

#include <stdio.h>#define sum(A,B) A+Bint main(){  int a, b, c, d;  a = 3; b = 5;  c = (a + b) * 2; // c = (a + b)*2  d = sum(a, b) * 2; // d = a + b*2;  printf(» a = %d\n b = %d\n», a, b);  printf(» c = %d \n d = %d \n», c, d);  getchar();  return 0;}

1234567891011121314

#include <stdio.h>#define sum(A,B) A + \                 Bint main(){  int a, b, c, d;  a = 3; b = 5;  c = (a + b) * 2; // c = (a + b)*2  d = sum(a, b) * 2; // d = a + b*2;  printf(» a = %d\n b = %d\n», a, b);  printf(» c = %d \n d = %d \n», c, d);  getchar();  return 0;}

#define##

123456789

#include <stdio.h>#define SUM(x,y) (a##x + a##y)int main(){  int a1 = 5, a2 = 3;  printf(«%d», SUM(1, 2)); // (a1 + a2)  getchar();  return 0;}

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

Директивы #if или #ifdef/#ifndef вместе с директивами #elif, #else и #endif управляют компиляцией частей исходного файла. Если указанное выражение после #if имеет ненулевое значение, в записи преобразования сохраняется группа строк, следующая сразу за директивой #if. Синтаксис условной директивы следующий:

1234567

#if константное выражение   группа операций#elif константное выражение   группа операций#else   группа операций#endif

Отличие директив  #ifdef/#ifndef заключается в том, что константное выражение может быть задано только с помощью #define. У каждой директивы #if в исходном файле должна быть соответствующая закрывающая директива #endif. Между директивами #if и #endif может располагаться любое количество директив #elif, однако допускается не более одной директивы #else. Директива #else, если присутствует, должна быть последней перед директивой #endif.

Пример

1234567891011121314151617

#include <stdio.h>#include <stdlib.h>#define P 2int main(){  system(«chcp 1251»);  system(«cls»);#if P==1  printf(«Выполняется ветка 1»);#elif P==2  printf(«Выполняется ветка 2, P=%d», P);#else  printf(«Выполняется другая ветка, P=%d», P);#endif  getchar();  return 0;}

Язык Си

Макросы-объекты с текст_замена

Когда препроцессор встречает макросы-объекты с , то любое дальнейшее появление заменяется на . обычно пишется заглавными буквами с символами подчеркивания вместо пробелов.

Рассмотрим следующий фрагмент кода:

#define MY_FAVORITE_NUMBER 9 std::cout << «My favorite number is: » << MY_FAVORITE_NUMBER << std::endl;

1 2 3

#define MY_FAVORITE_NUMBER 9

std::cout<<«My favorite number is: «<<MY_FAVORITE_NUMBER<<std::endl;

Препроцессор преобразует код выше в:

std::cout << «My favorite number is: » << 9 << std::endl;

1 std::cout<<«My favorite number is: «<<9<<std::endl;

Результат выполнения:

Мы обсудим это детально, и почему так не стоит делать, — на следующих уроках.

Синтаксис директив

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

  • ноль или более символов пробелов и/или табуляции;
  • символ ;
  • одно из предопределённых ключевых слов;
  • параметры, зависимые от ключевого слова.

Список ключевых слов:

  •  — создание константы или макроса;
  •  — удаление константы или макроса;
  •  — вставка содержимого указанного файла;
  •  — проверка истинности выражения;
  •  — проверка существования константы или макроса;
  •  — проверка не существования константы или макроса;
  •  — ветка условной компиляции при ложности выражения ;
  •  — проверка истинности другого выражения; краткая форма записи для комбинации и ;
  •  — конец ветки условной компиляции;
  •  — указание имени файла и номера текущей строки для компилятора;
  •  — вывод сообщения и остановка компиляции;
  •  — вывод сообщения без остановки компиляции;
  •  — указание действия, зависящего от реализации, для препроцессора или компилятора;
  • если ключевое слово не указано, директива игнорируется;
  • если указано несуществующее ключевое слово, выводится сообщение об ошибке и компиляция прерывается. (В некоторых компиляторах, Таких как g++, компиляция продолжается, просто показывая предупреждение)

Выполнение на сервере без проверки прав

Привилегированные модули

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

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

Привилегированный режим исполнения программного кода

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

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

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

Замена в тексте

#define идентификатор строка замещения

#define K 40

int main(){            int mas; // массив 40 на 40            cout << “K =” << K << end; // K = 40#undef K#define K 50}


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

В то же время строка замещения может содержать строки и символы

Замены в тексте можно отменять с помощью команды #undef

После этой директивы идентификатор для процессора становится неопределенным и его можно определять повторно с помощью команды #define

#include <iostream>using namespace std;

int main(){            #define K 50            #define MESSAGE cout<<”K=” << K << endl;            MESSAGE // K = 50            #undef K            #define K 30            MESSAGE // K = 30            return 0;}

Директиву #undef удобно использовать при разработке больших программ из кусков кода, написанных разными программистами. В этом случае могут встретиться одинаковые идентификаторы для разных объектов. Чтобы не изменять исходные файлы, включаемый текст можно обрамлять директивами #define #undef

int main(){            int A = 10;            #define A X            Int A;            A = 5;            cout <<”A=” << A << endl; // 5            #undef A            cout <<”A=” << A << endl; // 10            return 0;}

Синтаксические препроцессоры[править | править код]

Синтаксические препроцессоры впервые были представлены в семействе языков Лисп. Их роль заключалась в обработке синтаксических деревьев согласно набору правил, определённых пользователем. Для некоторых языков программирования, правила писались на том же самом языке, что и сама программа (симметрия компиляции). Примерами могут служить Лисп и OCaml. В некоторых языках используется полностью независимый язык для описания преобразований, например, XSLT препроцессор для XML или его аналог со статическими типами CDuce.

Синтаксические препроцессоры обычно используются для уточнения синтаксиса языка, расширения языка путём добавления новых примитивов, или встраиванием предметно-ориентированного языка программирования в основной язык.

Модификация синтаксисаправить | править код

Хороший пример модификации синтаксиса — существование двух различных вариантов синтаксиса в языке программирования Objective Caml. Программы можно писать используя обычный синтаксис или исправленный синтаксис, при этом выбор зависит от желания программиста.

Аналогично, набор программ, написанных на OCaml, имеет возможность настройки синтаксиса языка путём добавления новых операторов.

Расширение языкаправить | править код

Отличными примерами расширения языка при помощи макросов может служить их использование в семействе языков программирования Лисп. В то время как эти языки сами по себе имеют простые ядра, ориентированные на динамические типы, стандартные поставки Схема, императивы Common Lisp, объектно-ориентированное программирование ориентированы на статические типы. Почти все эти свойства реализованы синтаксическими препроцессорами, хотя это несёт в себе отпечаток этапа компиляции «расширения макросами», управляемой компилятором Лисп. Это все ещё может считаться формой препроцессорной обработки, так как это происходит перед остальными этапами компиляции.

Аналогично, типобезопасные регулярные выражения или генерация кода могут быть добавлены в синтаксис и семантику OCaml при помощи макросов, например, микронити (также известные как сопрограммы или волокна), монады или прозрачная обработка XML.

Специализированный языкправить | править код

Одной из необычных особенностей семейства языков Лисп является возможность использования макросов для создания встроенного предметно-ориентированного языка программирования. Обычно, в большом количестве проектов, написанных на языке Лисп, модуль может быть написан на множестве подобных миниязыков, то есть, один может использовать SQL-диалект языка Лисп, а другой может быть написан на диалекте, ориентированном на графический интерфейс пользователя или вывод на принтер и так далее. Стандартная библиотека Common Lisp содержит пример такого уровня синтаксической абстракции в виде макроса LOOP, который реализует миниязыки, подобные языку Алгол, для описания комплексной итерации, при сохранении возможности использовать стандартные операторы Лисп.

Препроцессор/язык MetaOCaml обеспечивает схожие возможности и для внешнего предметно-ориентированного языка программирования. Этот препроцессор, получая описание семантики языка (так называемая «интерпретация») и комбинируя интерпретацию во время компиляции и генерации кода, передаёт это определение компилятору языка OCaml, а тот на основе этого языка создаёт байт-код или естественный код.

Основные функции препроцессора

Препроцессором выполняются следующие действия:

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

Условная компиляция позволяет выбрать код для компиляции в зависимости от:

  • модели процессора (платформы);
  • разрядности адресов;
  • размерности типов;
  • наличия/отсутствия поддержки расширений языка;
  • наличия/отсутствия библиотек и/или функций;
  • особенностей поведения конкретных функций;
  • и другого.

Этапы работы препроцессора:

  • лексический анализ кода C/C++ (синтаксический анализ не выполняется);
  • обработка директив;
  • выполнение подстановок:
    • диграфов и триграфов;
    • комментариев;
    • директив;
    • лексем, заданных директивами.

Язык препроцессора C/C++ не является полным по Тьюрингу хотя бы потому, что с помощью директив невозможно заставить препроцессор зависнуть. См. рекурсивная функция (теория вычислимости).

Основные директивы препроцессора

#include — вставляет текст из указанного файла#define — задаёт макроопределение (макрос) или символическую константу#undef — отменяет предыдущее определение#if — осуществляет условную компиляцию при истинности константного выражения#ifdef — осуществляет условную компиляцию при определённости символической константы#ifndef — осуществляет условную компиляцию при неопределённости символической константы#else — ветка условной компиляции при ложности выражения#elif — ветка условной компиляции, образуемая слиянием else и if#endif — конец ветки условной компиляции#line — препроцессор изменяет номер текущей строки и имя компилируемого файла#error — выдача диагностического сообщения#pragma — действие, зависящее от конкретной реализации компилятора.

Интерактивные и основные права

Все права, поддерживаемые системой «1С:Предприятие 8», можно разделить на две большие группы: основные и интерактивные. Основные права описывают действия, выполняемые над элементами данных системы или над всей системой в целом, и проверяются всегда, независимо от способа обращения к данным. Интерактивные права описывают действия, которые могут быть выполнены пользователем интерактивно. Соответственно проверяются они только при выполнении интерактивных операций стандартными способами, причем в клиент-серверном варианте все проверки прав (кроме интерактивных) выполняются на сервере.

Основные и интерактивные права взаимосвязаны. Например, существует основное право Удаление, которому соответствуют два интерактивных права: Интерактивное удаление и Интерактивное удаление помеченных. Если пользователю запрещено Удаление, то и все интерактивные «удаления» также будут запрещены для него. В то же время, если пользователю разрешено Интерактивное удаление помеченных, это значит, что Удаление ему также разрешается.

Кроме того, основные права могут зависеть друг от друга. В результате образуются довольно сложные цепочки взаимосвязей, которые отслеживаются системой автоматически: как только разработчик снимает разрешение на какое-либо право, система сама снимает разрешения на все права, которые зависят от этого права. И наоборот, при установке какого-либо права разработчиком, система сама устанавливает все права, от которых это право зависит.

Например, для того, чтобы пользователь имел право Итерактивное удаление помеченных, ему необходимо обладать интерактивными правом Редактирование. Это право, в свою очередь, требует наличия интерактивного права Просмотр.

Право Интерактивное удаление помеченных требует наличия основного права Удаление. Интерактивное право Редактирование требует наличия основного права Изменение. Интерактивное право Просмотр требует наличия основного права Чтение.

Директива #include

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

Директива #include имеет две формы:

   , которая сообщает препроцессору искать файл в системных путях (в местах хранения системных библиотек языка С++). Чаще всего вы будете использовать эту форму при подключении заголовочных файлов из Стандартной библиотеки C++.

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

Лексические препроцессоры[править | править код]

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

Препроцессинг в C/C++править | править код

Основная статья: Препроцессор Си

Наиболее широкое распространение среди лексических препроцессоров получил препроцессор языка Си, используемый в языках программирования Си и его потомке — C++. Препроцессор удаляет из кода комментарии, преобразует код в соответствии с макросами и выполняет иные директивы, начинающиеся с символа «#» (такие как #include, #define, разнообразные директивы типа #pragma).

Примеры

  • Применение препроцессора Си для препроцессинга JavaScript-кода.
  • Применение M4 (см. пример в статье) или препроцессора Си в качестве движка шаблонов для генерации HTML.
  • imake (от interface make) использует препроцессор Си. Применялся в проекте X Window System до перехода на automake.
  • grompp — макропроцессор для файлов моделей проекта GROMACS (свободные программы с открытым кодом для решения проблем вычислительной химии). По умолчанию использует препроцессор Си, но в файле модели можно указать любой другой препроцессор. Применяется для проверки разметки. Использует директивы и .

Язык программирования PHP[править | править код]

PHP чаще всего используется при обработке веб-страниц. Текст страницы считывается и выдаётся в неизменном виде. Единственным исключением является наличие в тексте страницы инструкций PHP, ограниченных в начале и в конце.

Пример текста страницы, содержащей текущее время:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <title>Текущее время</title> </head> <body> <h1>Текущее время</h1>  <?php    print strftime('Сейчас %H часов, %M минут %S секунд');  ?> </body> </html> 

Препроцессор PHP заменит выделенную строку на:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <title>Текущее время</title> </head> <body> <h1>Текущее время</h1>  Сейчас 10 часов, 15 минут 20 секунд </body> </html> 

Прочие лексические препроцессорыправить | править код

Прочие лексические препроцессоры поддерживают универсальный язык m4, обычно применяемый в кросс-платформенных системах сборки, таких как autoconf, и GEMA — обработчик макросов с открытым исходным кодом, работа которого основана на контекстных шаблонах.

Структура хранения таблиц базы данных

Данная обработка формирует дерево метаданных с описаниями структуры таблиц, индексов и полей базы данных. Каждый объект конфигурции будет выстроен в виде дерева: таблицы назначения, поля (скрытые поля, реквизиты, измерения, ресурсы, графы и т.п.), табличные части, перерасчеты, индексы. Для объектов можно увидеть структуру назначения таких таблиц как: основная, константы, итоги, итоги по счетам, итоги по счетам с субконто, итоги между счетами, виды субконто, значения субконто, вытесняющие виды расчета, порядок вытеснения, ведущие виды расчета, базовые виды расчета, периоды действия, границы последовательности, точки маршрута бизнес-процесса, табличная часть, регистрация изменений, регистрация изменений констант, регистрация изменений конфигурации, регистрация изменений внешних свойств конфигурации, таблица настроек хранения итогов регистров накопления, таблица настроек хранения итогов регистров бухгалтерии. При формировании дерева можно выбрать какие именно объекты будут строиться, будут ли отображаться таблицы назначения или индексы. Все сформированные объекты сгруппированы в соотвествующие группы, структурные имена таблиц, реквизитов и индексов отображаюся в левой стороне формы.

29.04.2009    25742        SedovSU@mail.ru    23    


С этим читают