реклама на сайте
подробности

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> #define, вопросы по подстановке
Метценгерштейн
сообщение Jun 29 2015, 13:43
Сообщение #1


Профессионал
*****

Группа: Свой
Сообщений: 1 357
Регистрация: 12-04-05
Из: Петербург
Пользователь №: 4 079



немного не ясен момент один:

#define NUM 10
#define SUMM (NUM+8)

результат понятен.

А если поменять местами дефайны?
#define SUMM (NUM+8)
#define NUM 10

может ли препроцессор заглянуть вниз и увидеть, что NUM ниже есть у него? По описанию- не должен, но реально Keil проглатывает это.
Go to the top of the page
 
+Quote Post
zltigo
сообщение Jun 29 2015, 13:50
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 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
Go to the top of the page
 
+Quote Post
CrimsonPig
сообщение Jun 29 2015, 14:15
Сообщение #3


Местный
***

Группа: Участник
Сообщений: 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;

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

Вообще, ТС, завязывали бы вы с макросами, если возможно.. А то потом будете месяц искать глупую ошибку или еще хуже, эта глупая ошибка прокрадется в кхм... продакшен sm.gif из соседнего топика.
если у вас более-менее пристойный компилятор пользуйтесь константами и голова болеть не будет.

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
Go to the top of the page
 
+Quote Post
SSerge
сообщение Jun 29 2015, 14:24
Сообщение #4


Профессионал
*****

Группа: Свой
Сообщений: 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.
Go to the top of the page
 
+Quote Post
Метценгерштейн
сообщение Jun 29 2015, 14:33
Сообщение #5


Профессионал
*****

Группа: Свой
Сообщений: 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
с этим- надо скобочки ставить, окружающие буквы, чтобы содержимое А было как единое целое.
Go to the top of the page
 
+Quote Post
Mihey_K
сообщение Jun 29 2015, 14:34
Сообщение #6


Частый гость
**

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



Подтверждаю: GCC 4.8 ни единого предупреждения даже с опцией -Wall, результат 18.


--------------------
Блог о разработке на CC430, SIM900, GPS, ARM и не только...
Go to the top of the page
 
+Quote Post
CrimsonPig
сообщение Jun 29 2015, 14:55
Сообщение #7


Местный
***

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



Цитата(Метценгерштейн @ Jun 29 2015, 15:33) *
#define Min( A, B ) A<B ? A:B
с этим- надо скобочки ставить, окружающие буквы, чтобы содержимое А было как единое целое.


Очень хорошо! sm.gif
Но чтобы выполнить задание на твердую пятерку предлагаю рассмотреть еще случай из жизни:

int i=1;
int j =2;
int k = Min(++i, ++j);

и сравнить его со следующей имплементацией:

inline int Min_Better(int a1, a2) {return (a1<a2) ? a1: a2;}
Go to the top of the page
 
+Quote Post
Mihey_K
сообщение Jun 29 2015, 15:23
Сообщение #8


Частый гость
**

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



А это уже некорректно: Min(++i, ++j);
Подобную запись отцы не рекомендуют, страница 57.

Сообщение отредактировал Mihey_K - Jun 29 2015, 15:49


--------------------
Блог о разработке на CC430, SIM900, GPS, ARM и не только...
Go to the top of the page
 
+Quote Post
zltigo
сообщение Jun 29 2015, 16:11
Сообщение #9


Гуру
******

Группа: Свой
Сообщений: 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
Go to the top of the page
 
+Quote Post
Mihey_K
сообщение Jun 29 2015, 16:20
Сообщение #10


Частый гость
**

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



Цитата
начинается очевидная зависимость от реализации препроцессора

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


--------------------
Блог о разработке на CC430, SIM900, GPS, ARM и не только...
Go to the top of the page
 
+Quote Post
ViKo
сообщение Aug 28 2015, 10:44
Сообщение #11


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Не уверен, что вопрос уже не задавался, напишу в первой подходящей теме, потому что найти не реально.
Константами какой размерности оперирует препроцессор? unsigned int? Или можно задать суффикс ULL, и будет 64-битовое представление? Конкретно интересует Keil.

Проверил на примере #define TEST (1000000000000ULL / 1000000001)
Рассчитывает правильно. (А в том, что творю, что-то ломается. Но это мои косяки.)
Go to the top of the page
 
+Quote Post
Mihey_K
сообщение Aug 28 2015, 11:18
Сообщение #12


Частый гость
**

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



Все правильно вы сделали, LL для long long, и эта возможность определяется стандартом, а не компилятором. Базовый тип целочисленного представления числа без модификатора равен битности платформы, т. ё. по умолчанию int. Ссылка


--------------------
Блог о разработке на CC430, SIM900, GPS, ARM и не только...
Go to the top of the page
 
+Quote Post
ViKo
сообщение Aug 28 2015, 11:27
Сообщение #13


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Цитата(Mihey_K @ Aug 28 2015, 14:18) *
Все правильно вы сделали, LL для long long...

Спасибо. Дело было не в LL. Я уже тему создал по данному вопросу.
Go to the top of the page
 
+Quote Post
SSerge
сообщение Aug 28 2015, 11:47
Сообщение #14


Профессионал
*****

Группа: Свой
Сообщений: 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.
Go to the top of the page
 
+Quote Post
ViKo
сообщение Aug 28 2015, 12:24
Сообщение #15


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Что же он (препроцессор), то считает, то не считает..? rolleyes.gif Считал бы уже все подряд, помог бы компилятору.
Вот тема, просветила меня.
Go to the top of the page
 
+Quote Post

2 страниц V   1 2 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 27th July 2025 - 09:10
Рейтинг@Mail.ru


Страница сгенерированна за 0.01514 секунд с 7
ELECTRONIX ©2004-2016