Integro 0 17 апреля, 2019 Опубликовано 17 апреля, 2019 · Жалоба 1 hour ago, Arlleex said: Нет, так не работает. Какой компилятор? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 131 17 апреля, 2019 Опубликовано 17 апреля, 2019 · Жалоба Keil ARMCC. Но это не так важно. Еще раз: собрать в переменную результаты разворачивания #defines мне удалось, о чем я указал ранее. Однако преобразовать на лету все это дело еще и в строку средствами препроцессора, как тут верно заметили, нельзя. Если все-таки кому-то кажется, что можно - попробуйте в любом компиляторе Если каким-то образом получится, выкладывайте, лично я буду очень признателен Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Integro 0 19 апреля, 2019 Опубликовано 19 апреля, 2019 · Жалоба On 4/17/2019 at 10:19 PM, Arlleex said: Еще раз: собрать в переменную результаты разворачивания #defines мне удалось, о чем я указал ранее. Виноват, про строку что-то сразу не заметил. Но если действительно нужно сформировать строку в compile time здесь уже может помоч компилятор: #define BUILD_DATE (BUILD_DAY << 24 | BUILD_MONTH << 16 | BUILD_YEAR) #define BUILD_DAY ((uint32_t)((__DATE__[4] == ' ')?(__DATE__[5] - '0'):((__DATE__[4] - '0')*10 + (__DATE__[5] - '0')))) #define BUILD_MONTH ((uint32_t)((__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 ((uint32_t)((__DATE__[7] - '0')*1000 + (__DATE__[8] - '0')*100 + (__DATE__[9] - '0')*10 + (__DATE__[10] - '0'))) #define DIG_TO_CHAR(d) ((d)+'0') const uint32_t _day = BUILD_DAY; const uint32_t _month = BUILD_MONTH; const uint32_t _year = BUILD_YEAR; const char __DATE_RUS_FORMAT__[]= {DIG_TO_CHAR(_day / 10), DIG_TO_CHAR(_day % 10), '.', DIG_TO_CHAR(_month / 10), DIG_TO_CHAR(_month % 10), '.', DIG_TO_CHAR(_year / 1000 % 10), DIG_TO_CHAR(_year / 100 % 10), DIG_TO_CHAR(_year / 10 % 10), DIG_TO_CHAR(_year % 10), '\00'}; Как по мне, решение выглядит уродливо, но __DATE_RUS_FORMAT__ лежит уже расчитанный в секции с константами printf("Build date: %s\n",__DATE_RUS_FORMAT__); //Output: Build date: 19.04.2019 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 131 19 апреля, 2019 Опубликовано 19 апреля, 2019 · Жалоба Только что, Integro сказал: Как по мне, решение выглядит уродливо, но __DATE_RUS_FORMAT__ лежит уже расчитанный в секции с константами Да вот в том-то и проблемаЯ первым делом сделал так, как привели Вы. Но потом, подумав, что все это считается в build-time, решил, почему-бы не возложить это на препроцессор (лишние константы во Flash ни к чему). И вот тут грабли и вылезли Но все равно спасибо за ответ! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Integro 0 19 апреля, 2019 Опубликовано 19 апреля, 2019 · Жалоба 13 minutes ago, Arlleex said: лишние константы во Flash ни к чему Так не зависимо от того это #define "Some text" или const char text[]="Some text" строка с текстом будет будет храниться на Flash. Или речь о чем еще? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 186 19 апреля, 2019 Опубликовано 19 апреля, 2019 · Жалоба 2 минуты назад, Integro сказал: Так не зависимо от того это #define "Some text" или const char text[]="Some text" строка с текстом будет будет храниться на Flash. Или речь о чем еще? О том, что если в программе нужно только sizeof("Some text"), то для хранения во флешь нужен только один байт. А не столько сколько в const char text[]="Some text". И действий лишних в runtime не нужно. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Integro 0 19 апреля, 2019 Опубликовано 19 апреля, 2019 · Жалоба 9 minutes ago, jcxz said: О том, что если в программе нужно только sizeof("Some text"), то для хранения во флешь нужен только один байт. А не столько сколько в const char text[]="Some text". И действий лишних в runtime не нужно. Уважаемый @jcxz 1. Вопрос я задавал не Вам, и ваши догадки, вероятно, никак не коррелируют с мыслю автора 2. Ваш пример несостоятелен Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 186 19 апреля, 2019 Опубликовано 19 апреля, 2019 · Жалоба 7 минут назад, Integro сказал: 1. Вопрос я задавал не Вам, и ваши догадки, вероятно, никак не коррелируют с мыслю автора Мысль автора ясно читается из его постов. Странно что вы этого не понимаете. Автора не интересует само значение строки, а интересует данные производные от этого содержимого, которые бы считались на этапе компиляции. Это совершенно прозрачно читается из его постов. И тема эта как раз об этом. 7 минут назад, Integro сказал: 1. Вопрос я задавал не Вам PS: Форум принадлежит не вам. Свои правила тут диктовать никому ненужно. Если хотите задать личный вопрос - воспользуйтесь личными сообщениями. Или создайте свой форум. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 131 19 апреля, 2019 Опубликовано 19 апреля, 2019 · Жалоба Суть jcxz правильную уловил. В случае const uint32_t _day = BUILD_DAY; const uint32_t _month = BUILD_MONTH; const uint32_t _year = BUILD_YEAR; const char __DATE_RUS_FORMAT__[]= {DIG_TO_CHAR(_day / 10), DIG_TO_CHAR(_day % 10), '.', DIG_TO_CHAR(_month / 10), DIG_TO_CHAR(_month % 10), '.', DIG_TO_CHAR(_year / 1000 % 10), DIG_TO_CHAR(_year / 100 % 10), DIG_TO_CHAR(_year / 10 % 10), DIG_TO_CHAR(_year % 10), '\00'}; во Flash будут храниться: _day (4 байта), _month (4 байта), _year (тоже 4 байта), а также строка __DATE_RUS_FORMAT__. Из всего этого набора действительно нужна только строка __DATE_RUS_FORMAT__ (пока что). Получается, что первые три промежуточные константы попросту зря расходуют Flash (то, что 12 байт это копейки, это не важно). А хотелось сразу скомпилировать так, чтобы в __DATE_RUS_FORMAT__ лежала строка с датой и временем сборки (например, "19.04.2019 13:17:30"). Стандартная __DATE__ меня не устраивает по причине требования единообразности формата даты/времени на всех компилируемых программах без надстроек среды в виде изменения формата констант __DATE__, __TIME__ и других. К тому же, хотелось уметь соединять строки в любой последовательности (то есть что-то типа #define MY_DATE_TIME "строка 1" "строка 2" "..."). Вот и все, собственно. P.S. Товарищи, давайте жить дружно Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Integro 0 19 апреля, 2019 Опубликовано 19 апреля, 2019 · Жалоба 40 minutes ago, Arlleex said: во Flash будут храниться: _day (4 байта), _month (4 байта), _year (тоже 4 байта), Если эти переменные не нужны и нигде не используются, достаточно добавить ключевое слово static в объявления и линкер не положит эти переменные в выходной бинарь. Как раз под рукой ARMCC(ARM Compiler 5.06 update 5 (build 528)), результирующая информация(без какой либо оптимизации): const uint32_t _day = BUILD_DAY; const uint32_t _month = BUILD_MONTH; const uint32_t _year = BUILD_YEAR; //Выхлоп: //Total RO Size (Code + RO Data) 6988 ( 6.82kB) //Total RW Size (RW Data + ZI Data) 12284 ( 12.00kB) //Total ROM Size (Code + RO Data + RW Data) 7012 ( 6.85kB) static const uint32_t _day = BUILD_DAY; static const uint32_t _month = BUILD_MONTH; static const uint32_t _year = BUILD_YEAR; //Выхлоп: //Total RO Size (Code + RO Data) 6976 ( 6.81kB) //Total RW Size (RW Data + ZI Data) 12284 ( 12.00kB) //Total ROM Size (Code + RO Data + RW Data) 7000 ( 6.84kB) Минус 12 байт! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 119 19 апреля, 2019 Опубликовано 19 апреля, 2019 · Жалоба 44 минуты назад, Arlleex сказал: Суть jcxz правильную уловил. Сомневаюсь. Скорее вы не поняли, что он сказал Вы же сами ему противоречите: 44 минуты назад, Arlleex сказал: Из всего этого набора действительно нужна только строка __DATE_RUS_FORMAT__ (пока что). Он же утверждал, что эта строка вам не нужна. Да и безапелляционность его высказываний отнюдь не способствует. 44 минуты назад, Arlleex сказал: во Flash будут храниться: _day (4 байта), _month (4 байта), _year (тоже 4 байта), Вот теперь наконец стало понятно, что вам не нравится. static const uint32_t _day = BUILD_DAY; не спасает? Ну и вообще - вменяемый редактор связей должен выкинуть даже не-static переменные, на которые нет ссылок (для педантов: или каких-либо нестандартных указаний переменную не выкидывать), а на вашу _day после формирования __DATE_RUS_FORMAT__ ссылок вроде как не должно оставаться. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 186 19 апреля, 2019 Опубликовано 19 апреля, 2019 · Жалоба 16 минут назад, Сергей Борщ сказал: Сомневаюсь. Скорее вы не поняли, что он сказал Вы же сами ему противоречите: Или вы не поняли что сказал я.... Цитата Он же утверждал, что эта строка вам не нужна. Да и безапелляционность его высказываний отнюдь не способствует. Где я такое утверждал (что строка не нужна)??? Я сказал, что ТСу нужна (в данном конкретном месте) не сама строка, а некие производные от неё данные. И sizeof("...") привёл просто как простой и доходчивый пример таких производных данных. И это совсем не исключает того, что в каком-то другом месте программы эта самая строка нужна. И тема о том, как с помощью препроцессора получить производные данные от некоей строки на этапе build-time. PS: И в чём именно безапелляционность? В том, что я не писал через каждое слово "извиняюсь" и "смею предположить"? Так и вы не пишете - ваши высказывания тоже безапелляционны, таким образом. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 131 19 апреля, 2019 Опубликовано 19 апреля, 2019 · Жалоба Только что, Сергей Борщ сказал: Вы же сами ему противоречите Я полагал строку кода, а не строку Си. Строка кода, полученная в результате работы препроцессора, мне действительно не нужна. Именно так я понял jcxz. Чтобы отбросить все догадки, еще раз повторю, чего хотелось: 1. На этапе препроцессирования вычленить из константных строк __DATE__, __TIME__ полезное содержимое и переконвертировать их "налету" в другой формат ("19.04.2019 (... возможно какой-то текст или управляющие escape-последовательности) 14.00.05 (...)". Для этого я делаю соответствующие #defines BUILD_DAY, BUILD_MONTH, BUILD_YEAR. 2. Теперь я хотел также на этапе препроцессирования вот эти самые BUILD_DAY, BUILD_MONTH и BUILD_YEAR преобразовать в строку Си ("..." которая) с помощью директивы #. Очевидно, это не получилось. А нужно это было как раз для более читаемого формирования конечного результата: допустим, я бы хотел сформировать строку "1.0.5\r\nBuild date: 19.04.2019\r\nBuild time: 14:05:23\r\n". Для этого я хотел просто "слепить" несколько строк: #define REVISION "1.0.5" #define VERSION_STRING REVISION "\r\n" "Build date: " MAGIC_DATE(BUILD_DAY, BUILD_MONTH, BUILD_YEAR) "\r\n" " Build time: " MAGIC_TIME(BUILD_HOURS, BUILD_MINUTES, BUILD_SECONDS) "\r\n" где MAGIC_DATE и MAGIC_TIME как раз и есть те самые макросы, которые не захотели "разворачиваться" и тупо превращаться из строки кода в строку Си "...". Я ошибочно полагал, что BUILD_DAY, допустим, раз собирается на этапе build-time, то препроцессору заранее может быть известно о целочисленном значении этого параметра. Ошибку я свою понял и признаю. Конечная цель достигнута (как предложил уважаемый Integro), но не теми средствами, о которых я упоминал. Собрать строку побайтно, разумеется, мне приходило в голову, но я думал, что можно проще. P.S. Не думал, что возникнут какие-то недопонимания (возможно как с моей, так и с противоположных сторон). На первой странице как-то было очевиднее, что вопрос всеми понят правильно. Но для того это и Форум, чтобы обсуждать тонкости программерской кухни, ИМХО Всем спасибо! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 131 19 апреля, 2019 Опубликовано 19 апреля, 2019 · Жалоба Только что, Integro сказал: Минус 12 байт! Тогда можно еще ж проще: сразу подставлять, что нужно const char __TIME_RUS_FORMAT__[] = {DIG_TO_CHAR(BUILD_HOURS / 10), DIG_TO_CHAR(BUILD_HOURS % 10), ':', DIG_TO_CHAR(BUILD_MINUTES / 10), DIG_TO_CHAR(BUILD_MINUTES % 10), ':', DIG_TO_CHAR(BUILD_SECONDS / 10), DIG_TO_CHAR(BUILD_SECONDS % 10)}; вместо static const uint32_t _h = BUILD_HOURS; static const uint32_t _m = BUILD_MINUTES; static const uint32_t _s = BUILD_SECONDS; const char __TIME_RUS_FORMAT__[] = {DIG_TO_CHAR(_h / 10), DIG_TO_CHAR(_h % 10), ':', DIG_TO_CHAR(_m / 10), DIG_TO_CHAR(_m % 10), ':', DIG_TO_CHAR(_s / 10), DIG_TO_CHAR(_s % 10)}; Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Integro 0 19 апреля, 2019 Опубликовано 19 апреля, 2019 · Жалоба 32 minutes ago, Arlleex said: Для этого я хотел просто "слепить" несколько строк: #define REVISION "1.0.5" #define VERSION_STRING REVISION "\r\n" "Build date: " MAGIC_DATE(BUILD_DAY, BUILD_MONTH, BUILD_YEAR) "\r\n" " Build time: " MAGIC_TIME(BUILD_HOURS, BUILD_MINUTES, BUILD_SECONDS) "\r\n" Вот с этого нужно было начинать :) В итоге можно получить VERSION_STRING REVISION как строку но опять при помощи компилятора и через массив char заполняя его нужными символами, минус такого исполнения только один, выглядит криво, не так красиво как это мог сделать препроцессор. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться