|
#define, вопросы по подстановке |
|
|
|
Jun 29 2015, 13:50
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
QUOTE (Метценгерштейн @ Jun 29 2015, 16:43)  может ли препроцессор заглянуть вниз и увидеть, что NUM ниже есть у него? По описанию- не должен Не должен категорически и не делает этого. QUOTE , но реально Keil проглатывает это. Проглатывать и ПРАВИЛЬНО интерпретировать это разные вещи. Проглотить без предупреждения, приняв неопределнное значение за 0, может, если компилятор тупой или если предупреждения подавлены ( обычное дело для всяких "примеров" и "библиотек" ).
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Jun 29 2015, 14:15
|

Местный
  
Группа: Участник
Сообщений: 329
Регистрация: 23-04-14
Пользователь №: 81 502

|
Цитата(zltigo @ Jun 29 2015, 14:50)  Не должен категорически и не делает этого.
Проглатывать и ПРАВИЛЬНО интерпретировать это разные вещи. Проглотить без предупреждения, приняв неопределнное значение за 0, может, если компилятор тупой или если предупреждения подавлены ( обычное дело для всяких "примеров" и "библиотек" ). Да ладно... у меня VS2010 в режиме cpp съел это без проблем и выдал правильный ответ 18 #define SUMM (NUM+8) #define NUM 10 int aa = SUMM; Единственно, что мне бы ни за что не пришло в голову такое написать.... Вообще, ТС, завязывали бы вы с макросами, если возможно.. А то потом будете месяц искать глупую ошибку или еще хуже, эта глупая ошибка прокрадется в кхм... продакшен  из соседнего топика. если у вас более-менее пристойный компилятор пользуйтесь константами и голова болеть не будет. const uint32 MyNumber = 10; const uint32 MyAnotherNumber = MyNumber+8; inline uint32 Sum(uint32 arg) {return arg + 8;} --- Вот вам небольшой пример макроса. Найдите в нем примерно 6 ошибок, которые приведут к неопределенному поведению вашей программы. #define Min( A, B ) A<B ? A:B
Сообщение отредактировал CrimsonPig - Jun 29 2015, 14:16
|
|
|
|
|
Jun 29 2015, 14:24
|
Профессионал
    
Группа: Свой
Сообщений: 1 719
Регистрация: 13-09-05
Из: Novosibirsk
Пользователь №: 8 528

|
Цитата(Метценгерштейн @ Jun 29 2015, 20:43)  может ли препроцессор заглянуть вниз и увидеть, что NUM ниже есть у него? По описанию- не должен, но реально Keil проглатывает это. Препроцессору не нужно никуда заглядывать, для него директива #define SUMM (NUM+8) значит следующее: запомнить что если в разбираемом тексте попадётся лексема SUMM, то заменить её на текст (NUM+8). При этом препроцессору не нужно знать что из себя представляет этот NUM, для него это просто три буквы. Только и всего. Аналогично и со вторым макроопределением. А вот когда ниже в тексте программы попадается имя макроопределения, то производится макроподстановка, после чего получившийся текст снова разбирается от начала макроподстановки и к этому тексту снова будут применяться имеющиеся на данный момент макроопределения, за исключением уже применённых (во избежание рекурсии). Хотя вот это место даже в стандарте описано так, что ничего непонятно. Порядок появления макроопределений в данном случае не важен, главное чтобы они оба уже встретились до того как понадобится их применение.
--------------------
Russia est omnis divisa in partes octo.
|
|
|
|
|
Jun 29 2015, 14:33
|
Профессионал
    
Группа: Свой
Сообщений: 1 357
Регистрация: 12-04-05
Из: Петербург
Пользователь №: 4 079

|
Цитата(SSerge @ Jun 29 2015, 17:24)  Препроцессору не нужно никуда заглядывать, для него директива #define SUMM (NUM+8) значит следующее: запомнить что если в разбираемом тексте попадётся лексема SUMM, то заменить её на текст (NUM+8). При этом препроцессору не нужно знать что из себя представляет этот NUM, для него это просто три буквы. Только и всего. Аналогично и со вторым макроопределением.
А вот когда ниже в тексте программы попадается имя макроопределения, то производится макроподстановка, после чего получившийся текст снова разбирается от начала макроподстановки и к этому тексту снова будут применяться имеющиеся на данный момент макроопределения, за исключением уже применённых (во избежание рекурсии). Хотя вот это место даже в стандарте описано так, что ничего непонятно.
Порядок появления макроопределений в данном случае не важен, главное чтобы они оба уже встретились до того как понадобится их применение. тогда да, все корректно понимает компилятор #define Min( A, B ) A<B ? A:B с этим- надо скобочки ставить, окружающие буквы, чтобы содержимое А было как единое целое.
|
|
|
|
|
Jun 29 2015, 14:55
|

Местный
  
Группа: Участник
Сообщений: 329
Регистрация: 23-04-14
Пользователь №: 81 502

|
Цитата(Метценгерштейн @ Jun 29 2015, 15:33)  #define Min( A, B ) A<B ? A:B с этим- надо скобочки ставить, окружающие буквы, чтобы содержимое А было как единое целое. Очень хорошо!  Но чтобы выполнить задание на твердую пятерку предлагаю рассмотреть еще случай из жизни: int i=1; int j =2; int k = Min(++i, ++j); и сравнить его со следующей имплементацией: inline int Min_Better(int a1, a2) {return (a1<a2) ? a1: a2;}
|
|
|
|
|
Jun 29 2015, 15:23
|

Частый гость
 
Группа: Участник
Сообщений: 156
Регистрация: 27-09-06
Из: Irkutsk
Пользователь №: 20 747

|
А это уже некорректно: Min(++i, ++j); Подобную запись отцы не рекомендуют, страница 57.
Сообщение отредактировал Mihey_K - Jun 29 2015, 15:49
--------------------
Блог о разработке на CC430, SIM900, GPS, ARM и не только...
|
|
|
|
|
Jun 29 2015, 16:11
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
QUOTE (Метценгерштейн @ Jun 29 2015, 17:33)  с этим- надо скобочки ставить, окружающие буквы, чтобы содержимое А было как единое целое. Без скобок - беда. Только вопрос, где их ставить - лучше привыкать ВСЕГДА АБСОЛЮТНО ВСЕГДА, АВТОМАТИЧЕСКИ НЕ ДУМАЯ, ставить их при #define этих самых A и иже с ними. Тогда не надо будет городить специально конструкции со скобками в выражениях, в которых они явно не требуются. QUOTE (Метценгерштейн @ Jun 29 2015, 17:33)  тогда да, все корректно понимает компилятор Ну для начала не компилятор, а препроцессор. И все-же НЕ обязан, поскольку, увы, начинается очевидная зависимость от реализации препроцессора. Как и Min(++i, ++j) от реализации компилятора. QUOTE (CrimsonPig @ Jun 29 2015, 17:15)  Вообще, ТС, завязывали бы вы с макросами, если возможно.. Категорически не могу согласиться. Мысли надо выражать максимально понятно себе и компилятору. Создавать код-макроме в рассчете, что "пристойный компилятор" заоптимизирует и уберет ненужности и глупости.
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Jun 29 2015, 16:20
|

Частый гость
 
Группа: Участник
Сообщений: 156
Регистрация: 27-09-06
Из: Irkutsk
Пользователь №: 20 747

|
Цитата начинается очевидная зависимость от реализации препроцессора Полностью согласен, использование конструкций, неопределенных стандартом языка, чревато непереносимостью кода даже между разными версиями одного компилятора.
--------------------
Блог о разработке на CC430, SIM900, GPS, ARM и не только...
|
|
|
|
|
Aug 28 2015, 11:47
|
Профессионал
    
Группа: Свой
Сообщений: 1 719
Регистрация: 13-09-05
Из: Novosibirsk
Пользователь №: 8 528

|
Цитата(ViKo @ Aug 28 2015, 17:44)  Проверил на примере #define TEST (1000000000000ULL / 1000000001) Рассчитывает правильно. (А в том, что творю, что-то ломается. Но это мои косяки.) В этом примере препроцессор ничего не считает, а просто заменяет одни буквы на другие. Считать будет потом компилятор, разумеется как положено в языке С. Другое дело, если написать что-то вроде #if constant_expressionтогда считать придётся уже препроцессору. Как именно он это считает должно быть описано в доке на препроцессор.
--------------------
Russia est omnis divisa in partes octo.
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|