моя контактная информация
Почтамезофия@protonmail.com
2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
Есть некоторые настройки на языке C.Предопределенные символы, можно использовать напрямую, предопределенные символы:在预处理期间处理的
。
__FILE__ //进行编译的源文件
__LINE__ //文件当前的行号
__DATE__ //文件被编译日期
__TIME__ //文件被编译那一瞬的时间
__STDC__ //如果编译器遵循ANSI C(标准C),其值为1,否则未定义(报错)
Пример:
#include<stdio.h>
int main()
{
printf("%sn", __FILE__);
printf("%dn", __LINE__);
printf("%sn", __DATE__);
printf("%sn", __TIME__);
return 0;
}
результат операции:
Здесь хотелось бы упомянуть, что VS не полностью поддерживает ANSI C (стандарт C); gcc gccгкопий Поддерживает ANSI C (стандарт C)
Основной синтаксис:
# define name stuff
например:
#define MAX 100
#define reg register // 为 register 这个关键字创建一个简短的名字
#define do_forever for(;;) //用更形象的符号来替换一种实现
#define CASE break;case //在写 case 语句的时候自动吧 break 写上
//如果定义的 stuff 过长,可以分成几行写,除了最后一行外,每行的后面都加一个反斜杠(续行符)
#define DEBUG_PRINT printf("file:%stline:%dt
date:%sttime:%sn" ,
__FILE__,__LINE__ ,
__DATE__,__TIME__ )
- Второе предложение - лень, почему?
- Третье предложение для дляфили Круговой
初始化、判断、调整都可以省略
, но если суждение опущено, это означает, что условие суждения всегда истинно, т.е.бесконечная петля- В четвертой игре этого лучше не делать, это запросто может навлечь беду.
- Пятое предложениесимвол продолжения строкиИменно в предотвращении проблем после ветвления. Суть его в том.
转义
Назад回车符
, так что возврат каретки больше не является возвратом каретки.После символа продолжения строки ничего быть не может, нажмите“”
Просто нажмите Enter, иначе продолжением не будет следующая строка кода.
Теперь возникает проблема: используйте # определить определитьгефве При определении идентификатора следует ли добавлять его в конце?;
?
например:
#define MAX 1000
#define MAX 1000;
int main()
{
int n = MAX;
return 0;
}
Приведенный выше код плюс;
, это кажется немного излишним, но на работу программы это не влияет.
Кажется, добавлено;
Или не добавляй;
Все будет в порядке?
это действительно так?
Давайте посмотрим на следующий пример:
//例一
int main()
{
printf("%dn", MAX);
return 0;
}
//例二
int mian()
{
int max = 0;
if (1)
max = MAX;
else
max = 1;
return 0
}
После замены:
printf("%dn", 1000;);
Распечатать1000;
Что значит?
if (1)
max = 1000;
;
else
max = 1;
еще ещеелсе Кому соответствовать?
Понимаете, здесь что-то не так, так чтоиспользовать # определить определитьгефве При определении индикатора не добавляйте его после;
# определить определитьгефве Этот механизм включает положение,允许把参数替换到文本中
, эту реализацию часто называютМакрос ( Марко ) ( Марко )(марко)или Определить макрос ( definemacro ) ( определить макрос )(гефвемакро)
Разница между макросами и идентификаторами определений макросов, приведенными выше, заключается в следующем:Макрос имеет параметры
Вот как объявляется макрос:
#define name(parament - list) stuff
один из них парамент параментпарявляюсьент - список списокляст(список параметров) — это список символов, разделенных запятыми, которые могут встречаться в вещи вещисттыфф середина
Примечание: парамент параментпарявляюсьент - список списокляст(список параметров)Левая скобкаДолжно быть с имя имянаме рядом с, если между ними есть пробелы, список аргументов интерпретируется как вещи вещисттыфф часть.
Пример:
//实现一个宏,计算一个数的平方
#define SQUARE(x) x*x
int main()
{
int a = 5;
int ret = SQUARE(a);
printf("%dn", ret);
return 0;
}
результат операции:
Как видите, квадрат 5 рассчитан правильно.
Но на самом деле в приведенном выше коде есть проблема. См. следующий фрагмент кода:
int a = 5;
printf("%dn", SQUARE(a + 1));
результат операции:
Почему это так? Результат 5+1 равен 36, а 6 ∗ * ∗ 6 должно быть 36. Как вы получили 11?
Проблема в макросах, мы знаем宏是直接替换
, то результатом непосредственной замены приведенного выше кода будет:
printf("%dn", a+1*a+1);
5+6+1, результат естественно 11
Мы можем легко решить эту проблему, добавив круглые скобки с обеих сторон определения макроса.
#define SQUARE(x) (x)*(x)
Так нет ли проблем с этим определением?Давайте посмотрим на следующее определение макроса:
#define DOUBLE(X) (X)+(X)
Мы использовали круглые скобки в определении, чтобы избежать предыдущей проблемы, но этот макрос может вызвать новые ошибки.
int a = 5;
printf("%dn", 10 * DOUBLE(a));
результат операции:
Результат вывода не 100, а 55. Причина аналогична вышеуказанной. Приоритетный вопрос
Решение:
#define DOUBLE(X) ((X)+(X))
Таким образом, при использовании макросовНикогда не экономьте на скобкахчтобы избежать непредвиденных взаимодействий между операторами в параметрах или соседними операторами при использовании макросов.
Если параметр макроса встречается в определении макроса более одного раза, если параметр имеетпобочный эффект, то при использовании этого макроса вы можете подвергнуться опасности, что приведет к不可预测
результат. Побочные эффекты — это постоянные эффекты при вычислении выражения.
Например:
x + 1; //不带副作用
x++; //带副作用
Следующий макрос MAX демонстрирует проблемы, вызванные параметрами с побочными эффектами.
#define MAX(a,b) ((a) > (b) ? (a):(b))
int main()
{
int x = 5;
int y = 8;
int z = MAX(x++, y++);
printf("x=%d, y=%d, z=%dn", x, y, z);
return 0;
}
результат операции:
Почему это так?Давайте проанализируем это вместе
z = ((X++) > (y++) ? (x++) : (y++))
- Сначала вынеси решение: ххИкс++ с ггу++ суждение, потому что это постфикс ++, при суждении ххИкс 5, ггу равно 8, 8 > 5
- После суждения ххИкс 6, ггу за 9
- Затем выполните ггу ++, поскольку постфикс ++, результат 9
- Затем продолжайте ггу Выполнить автоинкремент, ггу Окончательный результат — 10.
мы будем ххИкс и ггу При передаче в макрос результаты изменились, особенно ггу, после двух изменений ты сказал, что это не страшно
Если в макрос передается параметр с побочными эффектами, и этот параметр появляется в макросе более одного раза, побочный эффект параметра также проявляется более одного раза.
Развернуть в программе № определить определитьгефве При определении символов и макросов необходимо выполнить несколько шагов.
参数进行检查
, посмотрите, содержит ли он # определить определитьгефве Определенный标识符
.Если да, то их заменяют в первую очередь.被插入
в исходное место в программе, заменяя имена параметров макросов их значениями#define MAX(a,b) ((a) > (b) ? (a):(b))
#define M 10
int main()
{
int x = 5;
int z = MAX(x, M);
return 0;
}
MAX в приведенном выше коде также обозначается # определить определитьгефве ОпределенныйМакрос .При последней проверке его параметр M был заменен. На этот раз пришло время его заменить.
МАКС ( х , 10 ) МАКС(х, 10)МАИкс(Икс,10) заменяется на ( ( х ) > ( 10 ) ((х) > (10)((Икс)>(10)
?
?
? ( х ) : ( 10 ) ) (х):(10))(Икс):(10))
конечно,宏里面嵌套宏
это тоже нормально
MAX(x, MAX(2, 3))
В это время сначала замените макрос в параметре, а затем замените весь макрос
Но следует отметить, что это不是递归
, который представляет собой просто макрос, служащий аргументом для другого макроса.递归是宏内部又调用了宏本身
。
Кроме того, когда препроцессор ищет # определить определитьгефве При определении символаСодержимое строковых констант не ищется
Что это значит?Просто дайте каштан и все поймете.
#define M 10
int main()
{
int x = 5;
int z = MAX(x, MAX(2, 3));
printf("M = %d", x);
return 0;
}
В приведенном выше кодеprintf("M = %d", x);
середина МММ не будет заменено на 10
Приведенный выше макрос используется для поиска большего значения двух чисел. Мы можем полностью записать его как функцию.
int Max(int x, int y)
{
return x > y ? x : y;
}
Мы обнаружили, что все они выполняют одну и ту же функцию.А вот для функции «найти большее из двух чисел» написание макроса будет更有优势
Некоторый
Есть две причины:
- используется для
调用函数
и函数返回
изкодможет занять больше времени, чем фактическое выполнение этого небольшого расчета (при вызове функцииСоздать кадр стека ).Поэтому функция макросоотношения есть в программе规模
и速度
Лучше, чем когда-либо- Важнее
函数的参数必须声明类型
, что приводит к использованию функции только для выражений соответствующего типа.Напротив, этот макрос можно применять ко многим типам: можно использовать целое число, длинное целое число, с плавающей запятой и т. д.
>
Сравнивать.Параметры макроса:Тип независимыйиз。
Всегда ли мы будем использовать макросы в будущем?Фактически макросы используются только дляПростой расчет, не подходит для сложных и больших операций и функций по сравнению с макросами Недостатки:
- Каждый раз, когда используется макрос, в программу вставляется копия кода определения макроса.Если макрос не относительно короткий, он может
大幅度增加程序的长度
- макрос это
没法调试
из- Макросы не зависят от типа, то есть
不够严谨
- Макросы могут вызвать проблемы с приоритетом операций, в результате чего программа
容易出错
Но иногда макросы могут делать то, чего не могут функции.
Например:
int* p = (int*)malloc(10 * sizeof * (int));
Нам не нравится так писать талок талокмаллос Функция слишком громоздкая, я хочу大小
и类型
Передайте его, чтобы освободить место
Malloc(10, int);
Могут ли функции сделать это?Нет потому чтоФункции не могут передавать типы
И макросы могут это сделать, потому что макросы этого не делают.Не проверятьваши параметрытипиз
#define Malloc(n, type) (type*)malloc(n * sizeof(type))
int main()
{
int* p = Malloc(10, int);
return 0;
}
Сравнение макросов и функций:
Атрибуты | # определить определитьгефвеОпределить макрос | функция |
---|---|---|
длина кода | При каждом использовании в программу будет вставляться код макроса. За исключением очень маленьких макросов, длина программы значительно увеличивается. | Значение кода функции появляется в одном месте, и каждый раз, когда функция используется, в этом месте вызывается один и тот же код. |
Скорость выполнения | Быстрее | Существуют дополнительные накладные расходы на вызовы и возвраты функций (открытие фреймов стека), поэтому давайте начнем с более медленных. |
приоритет оператора | Параметры макроса оцениваются в контексте всех окружающих выражений. Если не включены круглые скобки, приоритет соседних операторов может иметь непредсказуемые последствия. Поэтому рекомендуется писать макросы с большим количеством скобок. | Параметры функции оцениваются только один раз при вызове функции, а ее значение результата передается функции, что делает результат вычисления выражения более предсказуемым. |
Параметры с побочными эффектами | Параметры могут быть заменены на несколько позиций в макросе. Если параметры макроса оцениваются несколько раз, оценка параметров с побочными эффектами может привести к непредсказуемым результатам. | Параметры функции вызываются только один раз при передаче параметров, и результаты легче предсказать. |
Тип параметра | Параметры макроса не имеют никакого отношения к типу. Пока операция над параметрами разрешена, его можно использовать с любым типом параметра. | Параметры функции связаны с типом. Если параметры имеют разные типы, требуются разные функции, даже если они выполняют одну и ту же задачу. |
отлаживать | Макросы неудобно отлаживать | Функции можно отлаживать шаг за шагом. |
рекурсия | Макросы не могут быть рекурсивными | Функции могут быть рекурсивными |
Есть ли способ объединить их преимущества?
Представлено в C++встроенная функция встроенный встроенныйвлве —— Имеет преимущества как макросов, так и функций
Он выполняется так же быстро, как макрос, но имеет тот же эффект, что и функция.