Директива #define (C/C++)
#define создает макрос, который является связью идентификатора или параметризованного идентификатора со строкой токена. После определения макроса компилятор может подставить строку токена для каждого обнаруженного идентификатора в исходном файле.
Синтаксис
#define маркер-строкаидентификатора
#define идентификатор (идентификатор opt, . ,identifier opt)token-string opt
Замечания
Директива #define приводит компилятору заменить строку маркера для каждого вхождения идентификатора в исходном файле. Идентификатор заменяется только в том случае, если он формирует маркер. То есть идентификатор не заменяется, если он отображается в комментарии, в строке или в составе более длинного идентификатора. Дополнительные сведения см. в разделе «Токены».
Аргумент строки токена состоит из ряда маркеров, таких как ключевое слово, константы или полные операторы. Один или несколько символов пробелов должны отделять строку маркера от идентификатора. Эти пробелы не считаются частью замененного текста, как и все остальные пробелы, следующие за последним токеном текста.
Без #define строки маркера удаляется вхождения идентификатора из исходного файла. Идентификатор остается определенным и может быть проверен с помощью #if defined директив и #ifdef инструкций.
Вторая форма синтаксиса определяет макрос, подобный функции, с параметрами. Эта форма допускает использование необязательного списка параметров, которые должны находиться в скобках. После определения макроса каждое последующее вхождение идентификатора (opt , . идентификатор opt) заменяется версией аргумента строки токена, который имеет фактические аргументы, заменяемые формальными параметрами.
Имена формальных параметров отображаются в строке токена, чтобы пометить расположения, в которых заменяются фактические значения. Каждое имя параметра может отображаться несколько раз в строке маркера, и имена могут отображаться в любом порядке. Число аргументов в вызове должно соответствовать числу параметров в определении макроса. Надлежащее использование скобок обеспечит правильную обработку сложных фактических аргументов.
Формальные параметры в списке разделяются запятыми. Все имена в списке должны быть уникальными, и список должен быть заключен в скобки. Пробелы не могут разделять идентификатор и открываемую скобку. Используйте объединение строк — поместите обратную косую косую черту ( \ ) непосредственно перед новым символом — для длинных директив в нескольких исходных строках. Область формального имени параметра распространяется на новую строку, которая заканчивается строкой токена.
Если макрос определен во второй форме синтаксиса, последующие текстовые экземпляры, за которыми находится список аргументов, указывают на вызов макроса. Фактические аргументы, следующие за экземпляром идентификатора в исходном файле, соответствуют соответствующим формальным параметрам в определении макроса. Каждый формальный параметр в строке токена, который не предшествует строковой (), charizing ( #@ # ), или оператор вставки маркеров ( ## ) или не следует ## оператору, заменяется соответствующим фактическим аргументом. Перед заменой директивой формального параметра все макросы в фактическом аргументе разворачиваются. (Операторы описаны в разделе Операторы препроцессора.)
В следующих примерах макросов с аргументами показана вторая форма синтаксиса #define :
// Macro to define cursor lines #define CURSOR(top, bottom) (((top)
Аргументы с побочными эффектами иногда приводят к тому, что макросы дают непредвиденные результаты. Заданный формальный параметр может отображаться несколько раз в строке токена. Если этот формальный параметр заменяется выражением с побочными эффектами, выражение с такими эффектами может вычисляться несколько раз. (См. примеры в разделе Оператор вставки токенов (#).)
Директива #undef приводит к тому, что определение препроцессора идентификатора забывается. Дополнительные сведения см . в директиве #undef.
Если имя определяемого макроса происходит в строке маркера (даже в результате другого расширения макроса), он не расширяется.
Второй #define для макроса с тем же именем создает предупреждение, если только вторая последовательность маркеров не идентична первой.
Блок, относящийся только к системам Майкрософт
Если новое определение синтаксически совпадает с исходным, Microsoft C и C++ позволяют переопределить макрос. Другими словами, два определения могут иметь разные имена параметров. Это поведение отличается от ANSI C, которое требует, чтобы два определения были лексически идентичны.
Например, следующие два макроса идентичны, за исключением имен параметров. ANSI C не разрешает такое переопределение, но Microsoft C/C++ компилирует его без ошибок.
#define multiply( f1, f2 ) ( f1 * f2 ) #define multiply( a1, a2 ) ( a1 * a2 )
С другой стороны, следующие два макроса неидентичны и приводят к выдаче предупреждения в Microsoft C и C++.
#define multiply( f1, f2 ) ( f1 * f2 ) #define multiply( a1, a2 ) ( b1 * b2 )
Завершение блока, относящегося только к системам Майкрософт
В этом примере показана директива #define :
#define WIDTH 80 #define LENGTH ( WIDTH + 10 )
Первый оператор определяет идентификатор WIDTH как целочисленную константу 80, а затем LENGTH задается в виде WIDTH и целочисленной константы 10. Каждое вхождение LENGTH заменяется на ( WIDTH + 10 ). В свою очередь, каждое вхождение WIDTH + 10 заменяется выражением ( 80 + 10 ). Скобки вокруг WIDTH + 10 имеют важное значение, поскольку управляют интерпретацией в операторах, например в следующем:
var = LENGTH * 20;
После этапа предварительной обработки этот оператор принимает следующий вид:
var = ( 80 + 10 ) * 20;
что равно 1800. Без скобок результат будет следующим:
var = 80 + 10 * 20;
Блок, относящийся только к системам Майкрософт
Определение макросов и констант с параметром компилятора /D имеет тот же эффект, что и при использовании директивы предварительной обработки #define в начале файла. С помощью параметра /D можно определить до 30 макросов.
Завершение блока, относящегося только к системам Майкрософт
Математические константы
Корпорация Майкрософт предоставляет несколько предопределенных макросов препроцессора для общих математических констант.
Синтаксис
#define _USE_MATH_DEFINES // for C++ #include #define _USE_MATH_DEFINES // for C #include
Замечания
Определены символические обозначения для следующих величин:
| Символ | Expression | Значение |
|---|---|---|
| M_E | Д. | 2.71828182845904523536 |
| M_LOG2E | log2(e) | 1.44269504088896340736 |
| M_LOG10E | log10(e) | 0.434294481903251827651 |
| M_LN2 | ln(2) | 0.693147180559945309417 |
| M_LN10 | ln(10) | 2.30258509299404568402 |
| M_PI | pi | 3.14159265358979323846 |
| M_PI_2 | pi/2 | 1.57079632679489661923 |
| M_PI_4 | pi/4 | 0.785398163397448309616 |
| M_1_PI | 1/pi | 0.318309886183790671538 |
| M_2_PI | 2/pi | 0.636619772367581343076 |
| M_2_SQRTPI | 2/sqrt(pi) | 1.12837916709551257390 |
| M_SQRT2 | sqrt(2) | 1.41421356237309504880 |
| M_SQRT1_2 | 1/sqrt(2) | 0.707106781186547524401 |
Математические константы не определены в стандарте C/C++. Чтобы использовать их, сначала необходимо определить _USE_MATH_DEFINES , а затем включить или .
Файл включает в себя , когда проект построен в режиме выпуска. Если вы используете одну или несколько математических констант в проекте, который также включает , необходимо определить _USE_MATH_DEFINES перед включением .
Математическая библиотека языков C и C++
В стандартную математическую библиотеку языка Си (а, значит, и C++) входит множество специальных математических функций, которые нужно знать и уметь использовать. Для того, чтобы использовать эти функции в своей программе, необходимо подключить заголовочный файл, содержащий описания этих функций, что делается строчкой в начале программы:
#include
В языке C++ нужно указывать название заголовочного файла так:
#include
Функция от одного аргумента вызывается, например, так: sin(x) . Вместо числа x может быть любое число, переменная или выражение. Функция возвращает значение, которое можно вывести на экран, присвоить другой переменной или использовать в выражении:
y = sin(x);
printf("%lf", sqrt(2));
| Функция | Описание |
|---|---|
| Округление | |
| round | Округляет число по правилам арифметики, то есть round(1.5) == 2 , round(-1.5) == -2 |
| floor | Округляет число вниз (“пол”), при этом floor(1.5) == 1 , floor(-1.5) == -2 |
| ceil | Округляет число вверх (“потолок”), при этом ceil(1.5) == 2 , ceil(-1.5) == -1 |
| trunc | Округление в сторону нуля (отбрасывание дробной части), при этом trunc(1.5) == 1 , trunc(-1.5) == -1 |
| fabs | Модуль (абсолютная величина) |
| Корни, степени, логарифмы | |
| sqrt | Квадратный корень. Использование: sqrt(x) |
| cbrt | Кубический корень. Использование: cbrt(x) |
| pow | Возведение в степень, возвращает a b . Использование: pow(a,b) |
| exp | Экспонента, возвращает e x . Использование: exp(x) |
| log | Натуральный логарифм |
| log10 | Десятичный логарифм |
| Тригонометрия | |
| sin | Синус угла, задаваемого в радианах |
| cos | Косинус угла, задаваемого в радианах |
| tan | Тангенс угла, задаваемого в радианах |
| asin | Арксинус, возвращает значение в радианах |
| acos | Арккосинус, возвращает значение в радианах |
| atan | Арктангенс, возвращает значение в радианах |
Также в файле cmath есть набор полезных числовых констант, например, константа M_PI хранит значение числа \(\pi\).
В компиляторе Visual C++ для использования этих констант необходимо объявить директиву препроцессора _USE_MATH_DEFINES перед подключения заголовочного файла cmath .
#define _USE_MATH_DEFINES #include
Деление действительных чисел
Для действительных чисел определены операции сложения, вычитания, умножения и деления.
При этом операция деления выполняется по-разному для переменных и констант целочисленного типа и для переменных и констант действительных типов. В первом случае деление производится нацело с отбрасыванием дробной части, во втором случае — деление производится точно и результатом является действительное число. Более точно, если делимое и делитель одновременно являются целочисленными константами или переменными целочисленных типов, то деление будет целочисленным, а если хотя бы одно из них действительное, то деление будет действительным. Например:
printf("%lf\n", 10 / 3);
printf("%lf\n", 10. / 3);
printf("%lf\n", 10 / 3.);
printf("%lf\n", 10. / 3.);
выведет 3 в первой строке и 3.33333 в остальных строках.
Результат выполнения деления не зависит от того, какой переменной будет присвоен результат. Если написать double a = 10 / 3; , то переменная a будет равна 3, так как деление 10/3 будет целочисленным, независимо от того, чему будет присвоен результат.
Define use math defines c что это

work? How can you just magically define it like that and math constants will be available to you?
Is there something in cmath or math.h that checks if it is defined and based on that defines the math constants?
Also How do you look at the standard library files in Visual Studio?
Last edited on

Ok I googled it and figured out how it works.
It checks if you defined USE_MATH_DEFINES and based on that defines the constants.
It also checks if it is already DEFINED, I dont think it has to do this because pragma once and the include guards will prevent it from being included twice in a translation unit.
But here is the code that does that if anyone wants to see for future reference:
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
/* Define _USE_MATH_DEFINES before including math.h to expose these macro * definitions for common math constants. These are placed under an #ifdef * since these commonly-defined names are not part of the C/C++ standards. */ /* Definitions of useful mathematical constants * M_E - e * M_LOG2E - log2(e) * M_LOG10E - log10(e) * M_LN2 - ln(2) * M_LN10 - ln(10) * M_PI - pi * M_PI_2 - pi/2 * M_PI_4 - pi/4 * M_1_PI - 1/pi * M_2_PI - 2/pi * M_2_SQRTPI - 2/sqrt(pi) * M_SQRT2 - sqrt(2) * M_SQRT1_2 - 1/sqrt(2) */ /* _USE_MATH_DEFINES */