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

Keil ARMCC.

Но это не так важно.

Еще раз: собрать в переменную результаты разворачивания #defines мне удалось, о чем я указал ранее. Однако преобразовать на лету все это дело еще и в строку средствами препроцессора, как тут верно заметили, нельзя.

Если все-таки кому-то кажется, что можно - попробуйте в любом компиляторе:wink: Если каким-то образом получится, выкладывайте, лично я буду очень признателен:blush:

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


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

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

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


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

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

Как по мне, решение выглядит уродливо, но __DATE_RUS_FORMAT__ лежит уже расчитанный в секции с константами

Да вот в том-то и проблема:acute:Я первым делом сделал так, как привели Вы. Но потом, подумав, что все это считается в build-time, решил, почему-бы не возложить это на препроцессор (лишние константы во Flash ни к чему). И вот тут грабли и вылезли:whistle3: Но все равно спасибо за ответ!

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


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

13 minutes ago, Arlleex said:

лишние константы во Flash ни к чему

Так не зависимо от того это #define "Some text" или const char text[]="Some text" строка с текстом будет будет храниться на Flash. Или речь о чем еще?

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


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

2 минуты назад, Integro сказал:

Так не зависимо от того это #define "Some text" или const char text[]="Some text" строка с текстом будет будет храниться на Flash. Или речь о чем еще?

О том, что если в программе нужно только sizeof("Some text"), то для хранения во флешь нужен только один байт. А не столько сколько в const char text[]="Some text". И действий лишних в runtime не нужно.

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


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

9 minutes ago, jcxz said:

О том, что если в программе нужно только sizeof("Some text"), то для хранения во флешь нужен только один байт. А не столько сколько в const char text[]="Some text". И действий лишних в runtime не нужно.

Уважаемый @jcxz
1. Вопрос я задавал не Вам, и ваши догадки, вероятно, никак не коррелируют с мыслю автора
2. Ваш пример несостоятелен

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


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

7 минут назад, Integro сказал:

1. Вопрос я задавал не Вам, и ваши догадки, вероятно, никак не коррелируют с мыслю автора

Мысль автора ясно читается из его постов. Странно что вы этого не понимаете. Автора не интересует само значение строки, а интересует данные производные от этого содержимого, которые бы считались на этапе компиляции. Это совершенно прозрачно читается из его постов. И тема эта как раз об этом.

7 минут назад, Integro сказал:

1. Вопрос я задавал не Вам

PS: Форум принадлежит не вам. Свои правила тут диктовать никому ненужно. Если хотите задать личный вопрос - воспользуйтесь личными сообщениями. Или создайте свой форум.

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


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

Суть 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. Товарищи, давайте жить дружно:wink:

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


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

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 байт!

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


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

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

Суть jcxz правильную уловил.

Сомневаюсь. Скорее вы не поняли, что он сказал :blush: Вы же сами ему противоречите:

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__ ссылок вроде как не должно оставаться.

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


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

16 минут назад, Сергей Борщ сказал:

Сомневаюсь. Скорее вы не поняли, что он сказал :blush: Вы же сами ему противоречите:

Или вы не поняли что сказал я....

Цитата

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

Где я такое утверждал (что строка не нужна)??? :shok: 

Я сказал, что ТСу нужна (в данном конкретном месте) не сама строка, а некие производные от неё данные. И sizeof("...") привёл просто как простой и доходчивый пример таких производных данных. И это совсем не исключает того, что в каком-то другом месте программы эта самая строка нужна.

И тема о том, как с помощью препроцессора получить производные данные от некоей строки на этапе build-time.

 

PS: И в чём именно безапелляционность? В том, что я не писал через каждое слово "извиняюсь" и "смею предположить"? Так и вы не пишете - ваши высказывания тоже безапелляционны, таким образом.

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


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

Только что, Сергей Борщ сказал:

Вы же сами ему противоречите

Я полагал строку кода, а не строку Си. Строка кода, полученная в результате работы препроцессора, мне действительно не нужна. Именно так я понял 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. Не думал, что возникнут какие-то недопонимания (возможно как с моей, так и с противоположных сторон). На первой странице как-то было очевиднее, что вопрос всеми понят правильно. Но для того это и Форум, чтобы обсуждать тонкости программерской кухни, ИМХО:this:

 

Всем спасибо!

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


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

Только что, 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)};

:paint2:

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


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

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 заполняя его нужными символами, минус такого исполнения только один, выглядит криво, не так красиво как это мог сделать препроцессор.

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


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

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

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

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

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

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

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

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

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

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