Шаманъ 1 25 апреля, 2017 Опубликовано 25 апреля, 2017 (изменено) · Жалоба Приветствую всех! Исходные данные: Компоновщику (gnu ld) задаем некоторый символ. Например: -Xlinker --defsym -Xlinker __BUILD_DATE=0x$$(date +'%d%m%Y') В итоге &__BUILD_DATE = 0x25042017, сегодня :) В программе использование такой штуки тривиально, например: extern void __BUILD_DATE; .............. printf("Date: %X", (int)&__BUILD_DATE); Теперь вопрос. Все работает давно, но согласно стандарту С конструкция написанная выше неправильная (ибо объект не может быть c типом void). Но в реальности по тому адресу ведь действительно ничего нет, т.е. в смысловом плане она соответствует реальности. Можно void заменить на uint8_t или что-то подобное, тогда конструкция будет правильная с точки зрения С, но неправильная в смысловом плане. Хотелось бы узнать мнение у "знающих толк в извращениях" людей, как удовлетворить С и здравому смыслу :) P.S. Один вариант знаю, через неполный тип, вот так: extern struct _void_ __BUILD_DATE; но с этим вариантом не будет работать расширение GCC известное, как арифметика указателей. Для приведенного выше примера это не важно, но в более изощренных случаях это существенно. Короче хочется лаконичности и перфекционизма :), ну на крайний случай можно было бы просто отключить warning: taking address of expression of type 'void', но похоже он не отключаемый избирательно. Изменено 25 апреля, 2017 пользователем Шаманъ Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 136 25 апреля, 2017 Опубликовано 25 апреля, 2017 · Жалоба Можно так: extern char __BUILD_DATE[]; .............. printf("Date: %p", __BUILD_DATE); Со смысловым планом тут тоже не очень, но работать должно. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
scifi 1 26 апреля, 2017 Опубликовано 26 апреля, 2017 · Жалоба Всё не так. По феншую при сборке доп. утилита формирует хедер, в котором есть дата, ну а дальше как обычно. А ещё есть __DATE__. Кстати, "extern void foobar" - это забавно Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Шаманъ 1 26 апреля, 2017 Опубликовано 26 апреля, 2017 · Жалоба Можно так: extern char __BUILD_DATE[]; .............. printf("Date: %p", __BUILD_DATE); Со смысловым планом тут тоже не очень, но работать должно. Работает оно во всех случаях, но по смыслу самый подходящий вариант, который нарушает стандарт. Всё не так. По феншую при сборке доп. утилита формирует хедер, в котором есть дата, ну а дальше как обычно. Ну, а что делать с концом секции или с размером, которые определены в скрипте линкера? С точки зрения смысла они указывают в никуда, и для них extern void xxxx самое правильное определение. А ещё есть __DATE__. В данном случае мне нужна дата сборки, а __DATE__ даст дату компиляции файла к тому же в строковом представлении. Короче одновременно красиво и по стандарту не выходит. Сделал макросы, чтобы компилятор не ругался, но выглядит это, как костыли... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Baser 5 26 апреля, 2017 Опубликовано 26 апреля, 2017 · Жалоба __BUILD_DATE=0x$$(date +'%d%m%Y') В итоге &__BUILD_DATE = 0x25042017 Феншуем не владею, более того ну вааще не понял синтаксиса и как из первой строки получается вторая, ну да ладно. Все таки, чем __DATE__ не нравиться? В данном случае мне нужна дата сборки, а __DATE__ даст дату компиляции файла к тому же в строковом представлении. Если генерируете прошивку-релиз, то можно целиком перекомпилировать весь проект, чай не каждые пять минут это делаете, можно и подождать. А строку в цифру можно перегнать макросами (не мое, тут на форуме как-то пробегало): //==================================================================// #ifndef _COMPILE_DATE_TIME_ #define _COMPILE_DATE_TIME_ #define COMPILE_HOUR (((__TIME__[0]-'0')*10) + (__TIME__[1]-'0')) #define COMPILE_MINUTE (((__TIME__[3]-'0')*10) + (__TIME__[4]-'0')) #define COMPILE_SECOND (((__TIME__[6]-'0')*10) + (__TIME__[7]-'0')) #define COMPILE_YEAR ((((__DATE__[7]-'0')*10+(__DATE__[8]-'0'))*10+(__DATE__[9]-'0'))*10+(__DATE__[10]-'0')) #define COMPILE_MONTH ((__DATE__[2] == 'n' ? (__DATE__ [1] == 'a'? 0 : 5) \ : __DATE__[2] == 'b' ? 1 \ : __DATE__[2] == 'r' ? (__DATE__ [0] == 'M'? 2 : 3) \ : __DATE__[2] == 'y' ? 4 \ : __DATE__[2] == 'l' ? 6 \ : __DATE__[2] == 'g' ? 7 \ : __DATE__[2] == 'p' ? 8 \ : __DATE__[2] == 't' ? 9 \ : __DATE__[2] == 'v' ? 10 : 11)+1) #define COMPILE_DAY ((__DATE__[4]==' ' ? 0 : __DATE__[4]-'0')*10+(__DATE__[5]-'0')) #endif //==================================================================// Результат такой же: printf("%02u.%02u.%4u",COMPILE_DAY,COMPILE_MONTH,COMPILE_YEAR); 25.04.2017 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Шаманъ 1 27 апреля, 2017 Опубликовано 27 апреля, 2017 · Жалоба Феншуем не владею, более того ну вааще не понял синтаксиса и как из первой строки получается вторая, ну да ладно. Первая это кусочек из makefile, дата передается опцией компоновщику Все таки, чем __DATE__ не нравиться? Я ж вроде написал. Да и дата это только пример, в реальности много констант генерируются самим компоновщиком. Если генерируете прошивку-релиз, то можно целиком перекомпилировать весь проект, чай не каждые пять минут это делаете, можно и подождать. Дата+номер сборки дают однозначную информацию о версии. В принципе и номера сборки достаточно, но дата чаще нагляднее - глянул и сразу понятно. Впрочем номер сборки вводится таким же путем - по другому нельзя, т.к. иначе при изменении библиотек или ресурсов можно получить одинаковые номера сборок (номер генерируется автоматически через makefile). А строку в цифру можно перегнать макросами (не мое, тут на форуме как-то пробегало): Где-то наверное может быть полезным такой подход, но в данном случае это костыли. Вопрос то изначально был не столько о работоспособности (с чем проблем нет), а про красивый (лаконичный и отражающий смысл вкладываемый в него) код соответствующий стандартам С. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 235 17 мая, 2017 Опубликовано 17 мая, 2017 · Жалоба Ну, а что делать с концом секции или с размером, которые определены в скрипте линкера? С точки зрения смысла они указывают в никуда, и для них extern void xxxx самое правильное определение. Про GCC не знаю, но в IAR конец секции можно так: завести некую переменную (в отдельной секции), а в скрипте линкёра указать расположить эту секцию последней в регионе размещения: place in RAM_regionA {ro, first block IMAGE_HEAD, last section .codetail}; Насчёт переменных, определённых в скрипте линкёра можно так: положить их определения в отдельный *.h-файл и подключить этот файл к си-исходникам и к скрипту линкёра (линкёр IAR это позволяет). А с датой (или вообще для общего случая произвольных символов) самое правильное имхо - как указал scifi. Я именно так и делаю. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Шаманъ 1 18 мая, 2017 Опубликовано 18 мая, 2017 · Жалоба jcxz, тут больше вопрос не в том, как можно - сам знаю не один способ. Вариант с определением символов компоновщика вполне устраивает, просто программа написанная наиболее близко по смыслу не вписывается в стандарт С (хотя GCC все компилирует нормально, немного поругавшись). Вопрос скорее из серии перфекционизма :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Baser 5 18 мая, 2017 Опубликовано 18 мая, 2017 · Жалоба Вопрос скорее из серии перфекционизма :) Я бы сказал, что из серии крайнего перфекционизма. Мне бы не пришло в голову над такими вещами задумываться, хотя считаюсь педантичным человеком в глазах окружающих :) Кстати, ИАР на такие конструкции смотрит благосклонно, не выдавая никаких варнингов: ключ линкера --define_symbol __BUILD_DATE=0x25042017 или строки скрипта линкера define symbol __BUILD_DATE = 0x25042017; export symbol __BUILD_DATE; и в программе extern void __BUILD_DATE; ... printf("Date: %X", (int)&__BUILD_DATE); Это потому, что в ИАР такие пользовательские символы линкера явно обрабатываются отдельно. Компилятор же не позволит объявить неполный тип void __BUILD_DATE; А в случае пользовательского символа - пожалуйста, вот и нет предупреждений. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
scifi 1 18 мая, 2017 Опубликовано 18 мая, 2017 · Жалоба Вариант с определением символов компоновщика вполне устраивает, просто программа написанная наиболее близко по смыслу не вписывается в стандарт С (хотя GCC все компилирует нормально, немного поругавшись). Хочу поставить ЖЫРНУЮ точку. Значит, пользуемся фичей GCC, а именно определение символа с датой средствами компоновщика. Опять же, в GCC всё работает. Так что ещё тебе надо, любезный? Стандарт Си тут совсем сбоку, поскольку изначально речь идёт о GCC. В других средах другие дела. Короче, дело надо закрыть, так как нет состава преступления. За сим откланяюсь, Ваша Честь. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Шаманъ 1 18 мая, 2017 Опубликовано 18 мая, 2017 · Жалоба вот и нет предупреждений. В GCC более ранних версий предупреждений тоже не было, возможно у IAR все еще впереди :) Так что ещё тебе надо, любезный? Чтобы компилятор не ругался :) В реальности он у меня сейчас не ругается, но коряво это выглядит в коде, а когда красиво ругается. Стандарт Си тут совсем сбоку, поскольку изначально речь идёт о GCC. Нет. Он из-за стандарта ругается, ибо конструкция не по стандарту. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
LightElf 0 19 мая, 2017 Опубликовано 19 мая, 2017 · Жалоба Нет. Он из-за стандарта ругается, ибо конструкция не по стандарту. Тут уж надо определиться. Или по стандарту - и тогда никакой линкерной магии. Или с магией - но тогда не по стандарту. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Шаманъ 1 19 мая, 2017 Опубликовано 19 мая, 2017 · Жалоба Или по стандарту - и тогда никакой линкерной магии. Или с магией - но тогда не по стандарту. Ну да, или с магией, по стандарту, но с кривой программой. Нет гармонии :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться