Перейти к содержанию
    

Есть потребность автоматом собирать дату и время, но в нужном формате. Не суть.

А суть в том, что

#define TO_DATE_STR(x, y, z) _TO_DATE_STR(x, y, z)
#define _TO_DATE_STR(x, y, z) __TO_DATE_STR(#x, #y, #z)
#define __TO_DATE_STR(x, y, z) x":"y":"z

#define BUILD_D 10
#define BUILD_M 20
#define BUILD_Y 30

const char Vers[] = TO_DATE_STR(BUILD_D, BUILD_M, BUILD_Y);

дает в Vers "10:20:30". Все правильно.

 

Заменяя BUILD_D, BUILD_M, BUILD_Y на что-то более сложное (но все еще вычисляемое на этапе компиляции), например, на

#define BUILD_D ((u32)((__DATE__[4] == ' ')?(__DATE__[5] - '0'):((__DATE__[4] - '0')*10 + (__DATE__[5] - '0'))))

получаю в Vers "((u32)((__DATE__[4] == ' ')?(__DATE__[5] - '0'):((__DATE__[4] - '0')*10 + (__DATE__[5] - '0')))):20:30", то есть первый #define (BUILD_D) не распарсился в число, хотя я сделал двойной разворот макроса.

 

Не понимаю, почему он не разворачивает BUILD_D в конечное число...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

некоторые финты посмотреть там --

https://electronix.ru/forum/index.php?showtopic=68772

сам я в борьбе с препроцессором сдался, делаю нужный дефайн в make

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Макрос это подстановка строки. Никаких других "разворотов" не происходит и не должно происходить.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 час назад, Arlleex сказал:

получаю в Vers "((u32)((__DATE__[4] == ' ')?(__DATE__[5] - '0'):((__DATE__[4] - '0')*10 + (__DATE__[5] - '0')))):20:30", то есть первый #define (BUILD_D) не распарсился в число, хотя я сделал двойной разворот макроса.

И не должен был, потому что препроцессор не знает такой операции как (x == y) ? ...:...;  И операции индексирования он тоже не знает. Вы его с компилятором путаете.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

4 часа назад, rkit сказал:

Макрос это подстановка строки. Никаких других "разворотов" не происходит и не должно происходить.

Нет, не просто подстановка. Типичные разворачивания макроопределений хорошо видны при использовании, например, # и ##.

 

3 часа назад, jcxz сказал:

И не должен был, потому что препроцессор не знает такой операции как (x == y) ? ...:...;  И операции индексирования он тоже не знает. Вы его с компилятором путаете.

#define BUILD_DATE  (BUILD_DAY << 24 | BUILD_MONTH << 16 | BUILD_YEAR)


#define BUILD_DAY   ((u32)((__DATE__[4] == ' ')?(__DATE__[5] - '0'):((__DATE__[4] - '0')*10 + (__DATE__[5] - '0'))))
#define BUILD_MONTH ((u32)((__DATE__[0] == 'J' && __DATE__[1] == 'a' && __DATE__[2] == 'n')*1  + \
                                      (__DATE__[0] == 'F' && __DATE__[1] == 'e' && __DATE__[2] == 'b')*2  + \
                                      (__DATE__[0] == 'M' && __DATE__[1] == 'a' && __DATE__[2] == 'r')*3  + \
                                      (__DATE__[0] == 'A' && __DATE__[1] == 'p' && __DATE__[2] == 'r')*4  + \
                                      (__DATE__[0] == 'M' && __DATE__[1] == 'a' && __DATE__[2] == 'y')*5  + \
                                      (__DATE__[0] == 'J' && __DATE__[1] == 'u' && __DATE__[2] == 'n')*6  + \
                                      (__DATE__[0] == 'J' && __DATE__[1] == 'u' && __DATE__[2] == 'l')*7  + \
                                      (__DATE__[0] == 'A' && __DATE__[1] == 'u' && __DATE__[2] == 'g')*8  + \
                                      (__DATE__[0] == 'S' && __DATE__[1] == 'e' && __DATE__[2] == 'p')*9  + \
                                      (__DATE__[0] == 'O' && __DATE__[1] == 'c' && __DATE__[2] == 't')*10 + \
                                      (__DATE__[0] == 'N' && __DATE__[1] == 'o' && __DATE__[2] == 'v')*11 + \
                                      (__DATE__[0] == 'D' && __DATE__[1] == 'e' && __DATE__[2] == 'c')*12))
#define BUILD_YEAR  ((u32)((__DATE__[7] - '0')*1000 + (__DATE__[8] - '0')*100 + (__DATE__[9] - '0')*10 + (__DATE__[10] - '0')))

 

На глобальном уровне объявляю константу

const u32 Vers = BUILD_DATE;

и вижу под отладчиком в ней значение 0x0C0407E3 (12.04.2019).

 

То есть препроцессор развернул это выражение в одно число и подставил как инициализатор константы Vers. Значит - знает. Знает на этапе build-time. А строку сделать из него не может.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

10 минут назад, Arlleex сказал:

и вижу под отладчиком в ней значение 0x0C0407E3 (12.04.2019).

То есть препроцессор развернул это выражение в одно число и подставил как инициализатор константы Vers. Значит - знает. Знает на этапе build-time. А строку сделать из него не может.

Ключевое слово "под отладчиком". Это не препроцессор развернул, а компилятор. Я уже это говорил выше.

Прочитайте про этапы построения кода - что в какой последовательности выполняется: препроцессор, компилятор, компоновщик. И поймёте почему у вас так получилось как в первом посте.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А почему не посмотреть текст после препроцессора (перед компилятором) ?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Только что, jcxz сказал:

Ключевое слово "под отладчиком". Это не препроцессор развернул, а компилятор. Я уже это говорил выше.

Прочитайте про этапы построения кода - что в какой последовательности выполняется: препроцессор, компилятор, компоновщик. И поймёте почему у вас так получилось как в первом посте.

Да тогда понятно, в общем-то. Препроцессор не умеет вычислять. А компилятор умеет: если это возможно для данного выражения, он производит его build-time-вычисление и подставляет в нужные места.

Эх, жаль. И почему стандартописатели не предусмотрели мощную препроцессорную обработку:girl_cray2::biggrin:

 

Только что, x893 сказал:

А почему не посмотреть текст после препроцессора (перед компилятором) ?

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

15 минут назад, Arlleex сказал:

Эх, жаль. И почему стандартописатели не предусмотрели мощную препроцессорную обработку

Добавьте свою обработку, надо смотреть в IDE возможность вызова pre- и post- скриптов или других программ.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Большинство недостатков препроцессора С++ ( не С, к сожалению только С++ и 11+ версий) нивелируются constexpr выражениями и шаблонами.

Если у вас есть возможность использовать такие компиляторы то попробуйте, не пожалеете.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 hour ago, Arlleex said:

И почему стандартописатели не предусмотрели мощную препроцессорную обработку

Предусмотрели, но не в С препроцессоре. Берите M4 - он много где в Unix'ах используется

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

15 минут назад, xvr сказал:

Предусмотрели, но не в С препроцессоре. Берите M4 - он много где в Unix'ах используется

Спасибо, но, думаю, в моем случае это не совсем правильно: мне нужно без внешних скриптов/программ собирать такие строки и в armcc, и в gcc, и в C++ Builder (что у них там за компилятор не знаю).

Пожалуй, будет просто две константы во Flash лежать (дата и время сборки). Нужно будет упаковать - склею с нужными строками, а на приемнике распакую как больше нравится.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

#define _BUILD_D ((u32)((__DATE__[4] == ' ')?(__DATE__[5] - '0'):((__DATE__[4] - '0')*10 + (__DATE__[5] - '0'))))
#define BUILD_D _BUILD_D

 

так должно сработать. нужен ещё один уровень вложенности дефайна чтобы всё развернулось корректно.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

45 minutes ago, demiurg_spb said:

так должно сработать. нужен ещё один уровень вложенности дефайна чтобы всё развернулось корректно.

Плюсую, должно работать!)
 

On 4/12/2019 at 1:43 PM, Arlleex said:

Заменяя BUILD_D, BUILD_M, BUILD_Y на что-то более сложное (но все еще вычисляемое на этапе компиляции)

Как уже сказали, на этапе компиляции может вычислятся значение константы, а вот в результате работы препроцессора(для макроса выше, const u32 day = BUILD_D;) должно выйти что-то типо этого:

const u32 day = ((u32)(("Apr 17 2019"[4] == ' ')?("Apr 17 2019"[5] - '0'):(("Apr 17 2019"[4] - '0')*10 + ("Apr 17 2019"[5] - '0'))));

И как уже сказали, такое удобно смотреть в листинге препроцессора, флаг"-Е" для armcc и gcc (по дефолту результат положит в объектный файл и дальше компиляция будет остановлена с ошибкой) и опция generate preproccesor output для IAR, будет создан отдельный файл с расширением .i

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Цитата

так должно сработать. нужен ещё один уровень вложенности дефайна чтобы всё развернулось корректно.

Нет, так не работает.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...