Arlleex 131 12 апреля, 2019 Опубликовано 12 апреля, 2019 · Жалоба Есть потребность автоматом собирать дату и время, но в нужном формате. Не суть. А суть в том, что #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 в конечное число... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Vladivolt 0 12 апреля, 2019 Опубликовано 12 апреля, 2019 · Жалоба некоторые финты посмотреть там -- https://electronix.ru/forum/index.php?showtopic=68772 сам я в борьбе с препроцессором сдался, делаю нужный дефайн в make Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
rkit 1 12 апреля, 2019 Опубликовано 12 апреля, 2019 · Жалоба Макрос это подстановка строки. Никаких других "разворотов" не происходит и не должно происходить. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 184 12 апреля, 2019 Опубликовано 12 апреля, 2019 · Жалоба 1 час назад, Arlleex сказал: получаю в Vers "((u32)((__DATE__[4] == ' ')?(__DATE__[5] - '0'):((__DATE__[4] - '0')*10 + (__DATE__[5] - '0')))):20:30", то есть первый #define (BUILD_D) не распарсился в число, хотя я сделал двойной разворот макроса. И не должен был, потому что препроцессор не знает такой операции как (x == y) ? ...:...; И операции индексирования он тоже не знает. Вы его с компилятором путаете. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 131 12 апреля, 2019 Опубликовано 12 апреля, 2019 · Жалоба 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. А строку сделать из него не может. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 184 12 апреля, 2019 Опубликовано 12 апреля, 2019 · Жалоба 10 минут назад, Arlleex сказал: и вижу под отладчиком в ней значение 0x0C0407E3 (12.04.2019). То есть препроцессор развернул это выражение в одно число и подставил как инициализатор константы Vers. Значит - знает. Знает на этапе build-time. А строку сделать из него не может. Ключевое слово "под отладчиком". Это не препроцессор развернул, а компилятор. Я уже это говорил выше. Прочитайте про этапы построения кода - что в какой последовательности выполняется: препроцессор, компилятор, компоновщик. И поймёте почему у вас так получилось как в первом посте. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
x893 35 12 апреля, 2019 Опубликовано 12 апреля, 2019 · Жалоба А почему не посмотреть текст после препроцессора (перед компилятором) ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 131 12 апреля, 2019 Опубликовано 12 апреля, 2019 · Жалоба Только что, jcxz сказал: Ключевое слово "под отладчиком". Это не препроцессор развернул, а компилятор. Я уже это говорил выше. Прочитайте про этапы построения кода - что в какой последовательности выполняется: препроцессор, компилятор, компоновщик. И поймёте почему у вас так получилось как в первом посте. Да тогда понятно, в общем-то. Препроцессор не умеет вычислять. А компилятор умеет: если это возможно для данного выражения, он производит его build-time-вычисление и подставляет в нужные места. Эх, жаль. И почему стандартописатели не предусмотрели мощную препроцессорную обработку Только что, x893 сказал: А почему не посмотреть текст после препроцессора (перед компилятором) ? А что там смотреть? Все, что он выплюнул, я увидел в сформированной const-строке. Не увидев там желаемого, у меня и возник затуп. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
HardEgor 63 12 апреля, 2019 Опубликовано 12 апреля, 2019 · Жалоба 15 минут назад, Arlleex сказал: Эх, жаль. И почему стандартописатели не предусмотрели мощную препроцессорную обработку Добавьте свою обработку, надо смотреть в IDE возможность вызова pre- и post- скриптов или других программ. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Nixon 3 12 апреля, 2019 Опубликовано 12 апреля, 2019 · Жалоба Большинство недостатков препроцессора С++ ( не С, к сожалению только С++ и 11+ версий) нивелируются constexpr выражениями и шаблонами. Если у вас есть возможность использовать такие компиляторы то попробуйте, не пожалеете. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
xvr 12 12 апреля, 2019 Опубликовано 12 апреля, 2019 · Жалоба 1 hour ago, Arlleex said: И почему стандартописатели не предусмотрели мощную препроцессорную обработку Предусмотрели, но не в С препроцессоре. Берите M4 - он много где в Unix'ах используется Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 131 12 апреля, 2019 Опубликовано 12 апреля, 2019 · Жалоба 15 минут назад, xvr сказал: Предусмотрели, но не в С препроцессоре. Берите M4 - он много где в Unix'ах используется Спасибо, но, думаю, в моем случае это не совсем правильно: мне нужно без внешних скриптов/программ собирать такие строки и в armcc, и в gcc, и в C++ Builder (что у них там за компилятор не знаю). Пожалуй, будет просто две константы во Flash лежать (дата и время сборки). Нужно будет упаковать - склею с нужными строками, а на приемнике распакую как больше нравится. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
demiurg_spb 0 17 апреля, 2019 Опубликовано 17 апреля, 2019 · Жалоба #define _BUILD_D ((u32)((__DATE__[4] == ' ')?(__DATE__[5] - '0'):((__DATE__[4] - '0')*10 + (__DATE__[5] - '0')))) #define BUILD_D _BUILD_D так должно сработать. нужен ещё один уровень вложенности дефайна чтобы всё развернулось корректно. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Integro 0 17 апреля, 2019 Опубликовано 17 апреля, 2019 · Жалоба 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 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 131 17 апреля, 2019 Опубликовано 17 апреля, 2019 · Жалоба Цитата так должно сработать. нужен ещё один уровень вложенности дефайна чтобы всё развернулось корректно. Нет, так не работает. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться