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

 

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

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

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

Директива #include

Директива #include позволяет включать в текст программы указанный файл. Если заголовочный файл содержит описание библиотечных функций и находится в папке компилятора, он заключается в угловые скобки <>.
Если файл находится в текущем каталоге проекта, он указывается в кавычках «». Для файла, находящегося в другом каталоге необходимо в кавычках указать полный путь.

#include <stdio.h>
#include «func.c»

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

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

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

1
2
3
4
5
6
7
8

#include <stdio.h>
#define A 3
int 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)

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

Пример на Си: Вычисление синуса угла

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

#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;
}

Результат выполнения
Директива define

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

Однако при использовании таких макроопределений следует соблюдать осторожность, например

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

#include <stdio.h>
#define sum(A,B) A+B
int 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
По умолчанию текст макроопределения должен размещаться на одной строке. Если требуется перенести текст макроопределения на новую строку, то в конце текущей строки ставится символ «обратный слеш» — \.

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

#include <stdio.h>
#define sum(A,B) A + \
                 B
int 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 позволяет замещать часть идентификатора. Для указания замещаемой части используется ##.

1
2
3
4
5
6
7
8
9

#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;
}

Результат выполнения:
Использование ## в директиве #define

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

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

1
2
3
4
5
6
7

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

Отличие директив  #ifdef/#ifndef заключается в том, что константное выражение может быть задано только с помощью #define.

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

Пример

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

#include <stdio.h>
#include <stdlib.h>
#define P 2
int 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;
}

Результат выполнения
Условная компиляция

Назад: Язык Си

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

Последнее обновление: 07.01.2023

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

Прежде всего это такие директивы как #if/#else/#endif, действие которых напоминает условную конструкцию if:

#if условие
исходный_код
#endif

Если условие возвращает ненулевое значение (то есть оно истинно), то в итоговый исходный файл вставляется исходный код, который расположен между директивами
#if и #endif:

#include <stdio.h>
#define N 22

int main(void)
{
#if N==22
	printf("N=22");
#endif
	return 0;
}

Директива #else позволяет задать альтернативый код, который компилируется, если условие не верно:

#include <stdio.h>
#define N 22
 
int main(void)
{
#if N==22
    printf("N=22");
#else
    printf("N is undefined");
#endif
    return 0;
}

С помощью директивы #elif можно проверять дополнительные условия:

#include <stdio.h>
#define N 24

int main(void)
{
#if N==22
	printf("N = 22");
#elif N==24
	printf("N=24");
#else
	printf("N is undefined");
#endif
	return 0;
}

#ifdef

С помощью директивы #ifdef можно проверять, определен ли идентификатор, и если он определен, вставлять в исходный код определенный текст:

#include <stdio.h>
#define DEBUG

int main(void)
{
#ifdef DEBUG
	printf("Debug mode");
#endif
	return 0;
}

Обратным действием обладает директива #ifndef — она включает текст, если идентификатор не определен:

#include <stdio.h>
//#define DEBUG

int main(void)
{
#ifndef DEBUG
	printf("Production mode");
#else
	printf("Debug mode");
#endif
	return 0;
}

Если нам одновременно надо проверить значения двух идентификаторов, то можно использовать специальный оператор defined:

#include <stdio.h>
#define BETA
#define DEBUG

int main(void)
{
#if defined DEBUG && !defined BETA
	printf("debug mode; final version");
#elif defined DEBUG && defined BETA
	printf("debug mode; beta version");
#else
	printf("undefined mode");
#endif
	return 0;
}

From Wikipedia, the free encyclopedia

In computer programming, conditional compilation is a compilation technique which results in an executable program that is able to be altered by changing specified parameters. This technique is commonly used when these alterations to the program are needed to run it on different platforms, or with different versions of required libraries or hardware.

Many programming languages support conditional compilation. Typically compiler directives define or «undefine» certain variables; other directives test these variables and modify compilation accordingly. For example, not using an actual language, the compiler may be set to define «Macintosh» and undefine «PC», and the code may contain:

(* System generic code *)
if mac != Null then
    (* macOS specific code *)
else if pc != Null
    (* Windows specific code *)

In C and some languages with a similar syntax, this is done using an ‘#ifdef’ directive.

A similar procedure, using the name «conditional comment», is used by Microsoft Internet Explorer from version 5 to 9 to interpret HTML code. There is also a similar proprietary mechanism for adding conditional comments within JScript, known as conditional compilation.[1]

Criticism[edit]

When conditional compilation depends on too many variables, it can make the code harder to reason about as the number of possible combinations of configuration increases exponentially.[2][3][4] When conditional compilation is done via a preprocessor that does not guarantee syntactically correct output in the source language, such as the C preprocessor, this may lead to hard-to-debug compilation errors,[5][6][7] which is sometimes called «#ifdef hell.»[8][9]

References[edit]

  1. ^ «Conditional Compilation». Microsoft Corporation. Archived from the original on 2008-09-06. Retrieved 2011-11-27.
  2. ^ Gazzillo, Paul; Wei, Shiyi (2019-05-27). «Conditional Compilation is Dead, Long Live Conditional Compilation!» (PDF). ICSE-NIER ’19: Proceedings of the 41st International Conference on Software Engineering: New Ideas and Emerging Results. 2019 IEEE/ACM 41st International Conference on Software Engineering: New Ideas and Emerging Results (ICSE-NIER). Montreal, QC, Canada: IEEE Press. pp. 105–108. doi:10.1109/ICSE-NIER.2019.00035. ISBN 978-1-7281-1758-4. Archived (PDF) from the original on 2022-11-07. Retrieved 2023-01-21.
  3. ^ Meinicke, Jens; Thüm, Thomas; Schröter, Reimar; Benduhn, Fabian; Leich, Thomas; Saake, Gunter (2017). Meinicke, Jens; Thüm, Thomas; Schröter, Reimar; Benduhn, Fabian (eds.). Quality Assurance for Conditional Compilation. pp. 131–139. doi:10.1007/978-3-319-61443-4_12. ISBN 978-3-319-61443-4. Retrieved 2023-01-21.
  4. ^ «compiler — How does conditional compilation impact product quality, security and code complexity?». Software Engineering Stack Exchange. Retrieved 2023-01-21.
  5. ^ Le, Duc; Walkingshaw, Eric; Erwig, Martin (2011-09-18). #ifdef confirmed harmful: Promoting understandable software variation. 2011 IEEE Symposium on Visual Languages and Human-Centric Computing (VL/HCC). pp. 143–150. doi:10.1109/VLHCC.2011.6070391. ISBN 978-1-4577-1246-3.
  6. ^ «conditional compilation — Why should #ifdef be avoided in .c files?». Stack Overflow. Retrieved 2023-01-21.
  7. ^ «c++ — Dos and Don’ts of Conditional Compile». Stack Overflow. Retrieved 2023-01-21.
  8. ^ Preschern, Christopher (2019-07-03). Patterns to escape the #ifdef hell (PDF). Proceedings of the 24th European Conference on Pattern Languages of Programs. EuroPLop ’19. New York, NY, USA: Association for Computing Machinery. pp. 1–12. doi:10.1145/3361149.3361151. ISBN 978-1-4503-6206-1. Archived (PDF) from the original on 2022-12-21.
  9. ^ «Living in the #ifdef Hell». www.cqse.eu. 28 October 2015. Archived from the original on 2022-11-28. Retrieved 2023-01-21.

Содержание

  • 1. Директивы #if#else#elif#endif. Условная компиляция
    • 1.1. Комбинация директив #if — #endif
    • 1.2. Комбинация директив #if — #else — #endif
    • 1.3. Комбинация директив #if — #elif — #endif. Цепочка if-else-if
  • 2. Директивы #ifdef, #ifndef. Условная компиляция
  • 3. Оператор defined. Определение, существует ли в программе макроимя
  • Связанные темы

1. Директивы #if, #else, #elif, #endif. Условная компиляция
1.1. Комбинация директив #if — #endif

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

Общая форма директивы #if следующая

#if constant_expression
  operators_sequence
#endif

здесь

  • constant_expression – константное выражение, возвращающее true или false;
  • operator_sequence – последовательность операторов, выполняемая если constant_expression=true.

Пример.

#include <iostream>
using namespace std;

// Номер решения
#define N_SOLUTION 2

// Число Пі
#define Pi 3.1415926535

// Если решение равно 1, то вычислить длину окружности
#if N_SOLUTION == 1
#define RESULT(radius) 2*Pi*radius
#endif

// Если решение равно 2, то вычислить площадь круга
#if N_SOLUTION == 2
#define RESULT(radius) Pi*radius*radius
#endif

void main()
{
  // 1. Радиус
  double r;

  // 2. Ввести радиус окружности
  cout << "r = ";
  cin >> r;

  // 3. Вычислить площадь круга
  double area = RESULT(r);
  cout << "area = " << area << endl;
}

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

r = 3
area = 28.2743
 
1.2. Комбинация директив #if — #else — #endif

Директивы #if – #else – #endif позволяют откомпилировать одну из двух частей программы в зависимости от значения условного выражения. Общая форма использования данной директивы следующая:

#if consant_expression
  operators_sequence_1
#else
  operators_sequence_2
#endif

здесь

  • constant_expression – выражение, возвращающее значение логического типа (true или false);
  • operators_sequence_1 – последовательность операторов, которую нужно выполнить, если constant_expression=true;
  • operators_sequence_2 – последовательность операторов, которую нужно выполнить, если constant_expression=false.

Пример.

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

#include <iostream>
using namespace std;

// Номер решения
#define N_SOLUTION 1

// Число Пі
#define Pi 3.1415926535

// Если решение равно 1, то компилируется фрагмент, который вычисляет длину окружности,
// иначе компилируется фрагмент вычисляющий площадь окружности.
#if N_SOLUTION == 1
#define RESULT(radius) 2*Pi*radius
#else
#define RESULT(radius) Pi*radius*radius
#endif

void main()
{
  // 1. Радиус
  double r;

  // 2. Ввести радиус окружности
  cout << "r = ";
  cin >> r;

  // 3. Вычисление
  double result = RESULT(r);
  cout << "result = " << result << endl;
}

Результат

r = 3
result = 18.8496
 
1.3. Комбинация директив #if — #elif — #endif. Цепочка if-else-if

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

#if expression_1
  operators_sequence_1
#elif expression_2
  operators_sequence_2
...
#elif expression_N
  operators_sequence_N
#endif

здесь

  • expression_1, expression_2, expression_N – некоторое выражение, которое может бать истинно (true) или не истинно (false);
  • operators_sequence_1, operators_sequence_2, operators_sequence_N – последовательность операторов, которые нужно откомпилировать в соответствующем блоке кода.

Пример.

В примере, в зависимости от значения N_SOLUTION вычисляется соответствующая формула

#include <iostream>
using namespace std;

// Номер решения
#define N_SOLUTION 3

// Число Пі
#define Pi 3.1415926535

// Компилируется фрагмент, который соответствует номеру номеру решения.
#if N_SOLUTION == 1
#define RESULT(radius) 2*Pi*radius // длина окружности
#elif N_SOLUTION == 2
#define RESULT(radius) Pi*radius*radius // площадь круга
#elif N_SOLUTION == 3
#define RESULT(radius) 4.0/3*Pi*radius*radius*radius // объем шара
#endif

void main()
{
  // 1. Радиус
  double r;

  // 2. Ввести радиус окружности
  cout << "r = ";
  cin >> r;

  // 3. Вычисление
  double result = RESULT(r);
  cout << "result = " << result << endl;
}

Результат

r = 3
result = 113.097
 
2. Директивы #ifdef, #ifndef. Условная компиляция

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

Общий вид директив #ifdef:

#ifdef macros_name
  operators_sequence
#endif

здесь

  • macros_name – имя макроса, которое проверяется на то, определено ли оно оператором #define. Если имя макроса определено, выполняется последовательность operators_sequence;
  • operators_sequence – некоторая последовательность.

Общий вид директивы #ifndef:

#ifndef macros_name
  operators_sequence
#endif

здесь

  • macros_name – имя макроса, которое может быть определено или не определено. Если имя макроса определено директивой #define, то последовательность operator_sequence не выполняется;
  • operators_sequence – последовательность операторов.

Пример.

#include <iostream>
using namespace std;

#define Is_Calc_Length // Нужно ли определять макрос Length?

// Если нужно определить макрос, вычисляющий расстояние
// между двумя точками, то определить его
#ifdef Is_Calc_Length
#define Length(x1, y1, x2, y2) sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2))
#endif

// Если не нужно определять макрос Length, то вернуть 0
#ifndef Is_Calc_Length
#define Length(x1, y1, x2, y2) 0
#endif

void main()
{
  double x1, y1, x2, y2;
  cout << "x1 = "; cin >> x1;
  cout << "y1 = "; cin >> y1;
  cout << "x2 = "; cin >> x2;
  cout << "y2 = "; cin >> y2;

  double len = Length(x1, y1, x2, y2);
  cout << "len = " << len << endl;
}

Результат

x1 = 1
y1 = 2
x2 = 3
y2 = 5
len = 3.60555
 
3. Оператор defined. Определение, существует ли в программе макроимя

Оператор defined используется в сочетании с директивой #if. Сочетание этих двух элементов заменяет директиву #ifdef. Общая форма использования оператора defined имеет вид

defined macros_name

здесь

  • macros_name – имя макроса, которое проверяется на наличие.

Пример.

В примере демонстрируется оригинальный способ решений вычисления квадратного уравнения на основе предопределенных формул.

#include <iostream>
using namespace std;

// Оператор defined.
// Формули вычисления квадратного уравнения.
#define D(a, b, c) (b*b - 4*a*c)
#define X1(a, b, c) ((-b - sqrt(D(a,b,c))) / (2*a))
#define X2(a, b, c) ((-b + sqrt(D(a,b,c))) / (2*a))

void main()
{
  // Вычисление квадратного уравнения.
  // Проверка, есть ли формулы вычисления квадратного уравнения.
#if defined D
#if defined X1
#if defined X2
  // 1. Объявить переменные
  double a, b, c;

  // 2. Ввести коэффициенты
  cout << "a = "; cin >> a;
  cout << "b = "; cin >> b;
  cout << "c = "; cin >> c;

  // 3. Проверка, существует ли уравнение
  if (a == 0)
  {
    cout << "Incorrect value of a (a==0)." << endl;
    return;
  }

  // 4. Если дискриминант больше или равен 0, то произвести вычисление
  if (D(a, b, c) >= 0)
  {
    cout << "x1 = " << X1(a, b, c) << endl;
    cout << "x2 = " << X2(a, b, c) << endl;
  }
  else
    cout << "The equation has no roots." << endl;

#endif
#endif
#endif
}

Результат

a = -3
b = -4
c = 5
x1 = 0.7863
x2 = -2.11963
 

Связанные темы

  • Препроцессор. Общие сведения. Директивы препроцессора. Обзор. Директивы #define, #error, #include, #undef, #import, #using, #pragma, #line
  • Макросы. Директива #define. Примеры
 

Как
правило, отладка — это проверка работы
и исправление ошибок программистом
перед передачей проекта на тестирование.

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

В
набор инструментария отладки Visual Basic 6
входят такие основные инструменты, как:

  • панель инструментов
    Debug
    (Отладка)
    с кнопками команд для выполнения отладки
    приложения;

  • окно
    Immediate

    (Непосредственное выполнение),
    предназначенное для непосредственного
    ввода команд, требующих немедленного
    выполнения;

  • окно
    Watches

    (Наблюдение), предназначенное для
    просмотра значений выражений, включенных
    в список просмотра;

  • окно
    Locals

    (Локальные), предназначенное для
    просмотра значений переменных;

  • редактор кода со
    встроенными возможностями просмотра
    переменных, констант, свойств, выражений
    при отладке приложения в точках останова
    и пошаговом выполнении приложения;

  • окно
    Call Stack
    (Стек
    вызовов) для просмотра вызванных, но
    незавершенных процедур.

Панель
инструментов
Debug
(рис.
10.4) активизируется при выборе из меню
View
(Вид) команды
Toolbars
(Панели
инструментов), а затем значения Debug
(Отладка).

На
панели инструментов
Debug
находятся
кнопки, обеспечивающие работу по отладке
приложения. Назначение этих кнопок
описано в табл. 10.3.

Таблица
10.3.
Кнопки
панели инструментов

Debug

Кнопка

Название

Назначение

Start/Continue

(Продолжить)

Запускает
программу или продолжает ее выполнение
после прерывания

Break
(Остановка)

Вызывает
прерывание программы в необходимом
месте (без использования точек останова)

End(Завершение)

Завершает
выполнение программы

Toggle
Breakpoint

(Установить
точку останова)

Устанавливает
точку останова на текущей строке кода

Step
Into (Шаг с заходом в процедуры)

Осуществляет
пошаговое выполнение процедуры,
включая также вызываемые ею процедуры

Step
Over (Шаг без захода в процедуры)

Осуществляет
пошаговое выполнение процедуры без
трассировки вызываемых ею процедур

Step
Out (Шаг с выходом из процедуры)

Выполняет
пошаговое выполнение текущей процедуры
до выхода из нее

Locals
Window (Окно Locals)

Открывает
диалоговое окно Locals для контроля
значений переменных

Immediate
Window (Окно Immediate)

Открывает
окно Immediate для ввода и выполнения
команд

Watch
Window (Окно Watch)

Открывает
диалоговое окно Watches для просмотра
выражений, включенных в список
наблюдения

Quick
Watch

(Быстрый
просмотр)

Открывает
окно Quick Watch для просмотра выражения
и значения, которое оно возвращает в
данный момент в точке останова программы
или на определенном шаге при пошаговом
запуске программы

Call
Stack

(Стек
вызовов)

Открывает
окно Call Stack, в котором представлен
список выполняемых процедур

С
остальными инструментами вы сможете
познакомиться при рассмотрении процесса
отладки. Откройте любое из ранее
разработанных приложений, например
приложение для изучения записи/чтения
данных из файла. Установите точку
останова в процедуре записи данных. Для
этого щелкните кнопкой мыши, установив
указатель в сером вертикальном поле
редактора кода напротив интересующей
строки, или выполните команду
Toggle Break-point

(Установить точку останова) меню
Debug
(Отладка).
При этом в сером вертикальном поле рядом
с выбранной командой устанавливается
жирная точка (рис. 10.5), остановка выполнения
программы произойдет именно в этом
месте кода.

При
запуске программы в точке останова
выполнение программы приостанавливается
и для контроля работы приложения можно
использовать весь отладочный
инструментарий: просматривать значения
переменных и выражений при позиционировании
маркера на выбранной переменной или
выражении (рис. 10.6).

Для
более тщательного контроля работы
приложения можно использовать окна
просмотра:
Immediate

(Немедленное выполнение),
Watches

(Наблюдение),
Locals
(Локальные),
Quick Watch

(Быстрый просмотр).
Call Stack
(Стек
вызовов).

Кроме
прямого ввода и выполнения команд, окно
Immediate
служит
для выяснения значения переменных и
выражении. Для этого необходимо выполнить
команду ? с указанием интересующего
выражения, как это показано на рис. 10.7.
Значение выражения выводится в следующей
строке этого же окна.

При
работе с окном
Immediate
удобно
использовать объект Debug и его метод
print. В режиме запуска метод Debug. Print выводит
текстовое сообщение в окне
Immediate.

Синтаксис этого метода очень простой:

Debug.Print
StringMessage где StringMessage — текст выводимого
в окно
Immediate

сообщения.

В
окне Locals
можно просмотреть все переменные и их
значения, используемые в данный момент
приложением (рис. 10.8)

Основным
окном для просмотра значений выражений
является окно Watches
(рис. 10.9). В этом окне можно проконтролировать
любое выражение из списка введенных
для проверки.

Список
проверяемых выражений пополняется в
диалоговом окне
Add Watch
(рис.
10.10), открываемом командой
Add Watch
(Добавить
наблюдение) контекстного меню редактора
кода или одноименной кнопкой на панели
инструментов
Debug
(Отладка).
Для добавления выражения в список
контролируемых необходимо ввести его
в текстовое поле
Expression

(Выражение) этого окна.

Замечание

Если
в тексте кода выделить выражение, то
при вызове окна
Add Watch
это
выражение по умолчанию вставляется в
поле Expression.

Область
Context
диалогового
окна Add Watch
позволяет установить область видимости
переменных, наблюдаемых в выражении.
Раскрывающийся список
Procedure

(Процедура) задает видимость внутри
процедур, а список Module
(Модуль) — внутри программных модулей.

Переключатель
Watch Type
(Тип
просмотра) определяет, как Visual Basic
реагирует на наблюдаемое выражение.
При установке опции
Watch Expression

(Выражение наблюдения) значение выражения
отображается в диалоговом окне
Watches
в режиме
прерывания. Опция
Break When Value Is True
(Приостановить
при равенстве выражения значению
Истина)

автоматически задает режим прерываний
и обращение к контролю выражений при
условии равенства выражения значению
True
или
ненулевому значению для числовых
выражений. Опция
Break When Value Changes

(Приостановить при из менении значения
выражения) аналогична опции
Break When Value Is True,
но
приложение входит в режим прерывания
при изменении значения выражения.

В
дополнение к окну
Watches,
для
просмотра выражений можно использовать
окно Quick Watch
(Быстрый просмотр) для быстрого доступа
к значению выражения (рис. 10.11). Для этого
окна не требуется вводить список
контролируемых выражений, а достаточно
выделить интересующее выражение в
тексте кода и вызвать окно
Quick Watch

одноименной кнопкой на панели инструментов
Debug,

Для
контроля выполняемых процедур используется
окно Call
Stack (Стек вызовов), в котором показаны
все вызванные и активные в данный момент
процедуры (рис. 10.12).

Из
окна Call Stack
можно перейти к коду программы (рис.
10.13), откуда был выполнен вызов выбранной
в списке процедуры, с помощью кнопки
Show
(Показать). На рис. 10.13 показано место
вызова процедуры, выбранной в окне
Call Stack
(рис.
10.12).

Обработка
ошибок

Обработка
ошибок и неправильных действий
пользователя — обязательная составляющая
любого проекта. Для работы с ошибками
в Visual Basic 6 есть специальный оператор on
Error.

Существует
несколько вариантов синтаксиса этого
оператора. Первый
вариант
имеет
вид:

On
Error Go To StringLabel

где
StringLabel — метка оператора. Она должна
быть уникальной в пределах процедуры.

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

On
Error Go To ErrorLabel

текст
кода
процедуры
ErrorLabel:

Call
ErrorProcedure ()

End

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

Для
игнорирования ошибки необходимо
использовать следующий вариант оператора
on Error:

On
Error Resume Next

Для
того чтобы отключить обработку ошибок
в какой-либо процедуре, оператор on Error
записывается в виде:

On
Error Go To 0

При
обработке ошибок хорошо бы выдать
сообщение о том, что это за ошибка. Для
этого предназначены перечисленные ниже
встроенные возможности Visual Basic 6:

  • служебная переменная
    Err, которая содержит код ошибки;

  • служебная переменная
    Error, которая содержит текст системного
    сообщения об ошибке;

  • объект Err, который
    содержит одновременно код и сообщение
    об ошибке.

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

  • Resume Next

При
этом выполняется оператор, следующий
за оператором с ошибкой.

  • On Resume NextLabel

где
NextLabel — метка оператора, который будет
выполняться после обработки ошибки.

Приведенный
ниже код обрабатывает ошибки:

On
Error Go To ErrorLabel

текст
кода
процедуры

ErrorLabel:

Call
ErrorProcedure ()

Resume
NextStatement

текст
кода
процедуры

NextStatement:

текст
кода

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

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

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

Объявление
константы условной компиляции в коде
осуществляется при помощи директивы
#Const, а блоки кода для условной компиляции
обозначаются директивой #If…Then…#Else.
Например, для создания версий одного и
того же приложения на французском и
немецком языках из одного исходного
кода, необходимо внедрить зависимые от
платформы сегменты кода в инструкции
#If…Then с помощью определенных ранее
констант FrenchVersion и GermanVersion. Как это
сделать, показано в следующем примере:

Язык
Visual
Basic

#If
FrenchVersion
Then

‘ <code
specific to the French language version>.

#ElseIf
GermanVersion Then

‘ <code
specific to the German language version>.

#Else


<code specific to other versions>.

#End
If

Если
для константы задается FrenchVersion значение
True во время компиляции, компилируется
условный код для французской версии.
Если установить для константы GermanVersion
значение True, компилятор использует
немецкую версию. Если ни одна константа
не имеет значения True, выполняется код
в последнем блоке Else.Примечание.

Автозавершение
не работает при редактировании кода и
использовании директив условной
компиляции, если код не является частью
текущей ветви.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]

  • #
  • #
  • #
  • #
  • #
  • #
  • #
  • #
  • #
  • #
  • #

Понравилась статья? Поделить с друзьями:
  • Очиститель для стиральных машин dr beckmann инструкция по применению
  • Кофеварка скарлет инструкция по применению видео
  • Инструкция к мультиварке поларис рмс 0508d
  • Каково назначение инструкции по охране труда
  • Pocket scale mh 100 инструкция на русском