реклама на сайте
подробности

 
 
 
Reply to this topicStart new topic
> А как бы "феншуйно" использовать символы определяемые линкером?, или отключить warning: taking address of expression of type void
Шаманъ
сообщение Apr 25 2017, 18:46
Сообщение #1


Знающий
****

Группа: Участник
Сообщений: 758
Регистрация: 27-08-08
Пользователь №: 39 839



Приветствую всех!

Исходные данные:

Компоновщику (gnu ld) задаем некоторый символ. Например:
Код
-Xlinker --defsym -Xlinker __BUILD_DATE=0x$$(date +'%d%m%Y')

В итоге &__BUILD_DATE = 0x25042017, сегодня sm.gif

В программе использование такой штуки тривиально, например:
Код
extern void __BUILD_DATE;
..............
printf("Date: %X", (int)&__BUILD_DATE);


Теперь вопрос. Все работает давно, но согласно стандарту С конструкция написанная выше неправильная (ибо объект не может быть c типом void). Но в реальности по тому адресу ведь действительно ничего нет, т.е. в смысловом плане она соответствует реальности. Можно void заменить на uint8_t или что-то подобное, тогда конструкция будет правильная с точки зрения С, но неправильная в смысловом плане.

Хотелось бы узнать мнение у "знающих толк в извращениях" людей, как удовлетворить С и здравому смыслу sm.gif
P.S. Один вариант знаю, через неполный тип, вот так:
extern struct _void_ __BUILD_DATE;

но с этим вариантом не будет работать расширение GCC известное, как арифметика указателей. Для приведенного выше примера это не важно, но в более изощренных случаях это существенно.

Короче хочется лаконичности и перфекционизма sm.gif, ну на крайний случай можно было бы просто отключить warning: taking address of expression of type 'void', но похоже он не отключаемый избирательно.

Сообщение отредактировал Шаманъ - Apr 25 2017, 18:47
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Apr 25 2017, 19:28
Сообщение #2


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Можно так:
CODE
extern char __BUILD_DATE[];
..............
printf("Date: %p", __BUILD_DATE);
Со смысловым планом тут тоже не очень, но работать должно.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
scifi
сообщение Apr 26 2017, 07:08
Сообщение #3


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Всё не так. По феншую при сборке доп. утилита формирует хедер, в котором есть дата, ну а дальше как обычно.
А ещё есть __DATE__.
Кстати, "extern void foobar" - это забавно biggrin.gif
Go to the top of the page
 
+Quote Post
Шаманъ
сообщение Apr 26 2017, 15:43
Сообщение #4


Знающий
****

Группа: Участник
Сообщений: 758
Регистрация: 27-08-08
Пользователь №: 39 839



Цитата(Сергей Борщ @ Apr 25 2017, 22:28) *
Можно так:
Код
extern char __BUILD_DATE[];
..............
printf("Date: %p", __BUILD_DATE);
Со смысловым планом тут тоже не очень, но работать должно.

Работает оно во всех случаях, но по смыслу самый подходящий вариант, который нарушает стандарт.

Цитата(scifi @ Apr 26 2017, 10:08) *
Всё не так. По феншую при сборке доп. утилита формирует хедер, в котором есть дата, ну а дальше как обычно.

Ну, а что делать с концом секции или с размером, которые определены в скрипте линкера? С точки зрения смысла они указывают в никуда, и для них extern void xxxx самое правильное определение.

Цитата
А ещё есть __DATE__.

В данном случае мне нужна дата сборки, а __DATE__ даст дату компиляции файла к тому же в строковом представлении.

Короче одновременно красиво и по стандарту не выходит. Сделал макросы, чтобы компилятор не ругался, но выглядит это, как костыли...
Go to the top of the page
 
+Quote Post
Baser
сообщение Apr 26 2017, 16:23
Сообщение #5


Просто Che
*****

Группа: Свой
Сообщений: 1 567
Регистрация: 22-05-07
Из: ExUSSR
Пользователь №: 27 881



Цитата(Шаманъ @ Apr 25 2017, 21:46) *
__BUILD_DATE=0x$$(date +'%d%m%Y')
В итоге &__BUILD_DATE = 0x25042017

Феншуем не владею, более того ну вааще не понял синтаксиса и как из первой строки получается вторая, ну да ладно.
Все таки, чем __DATE__ не нравиться?

Цитата(Шаманъ @ Apr 26 2017, 18:43) *
В данном случае мне нужна дата сборки, а __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

Go to the top of the page
 
+Quote Post
Шаманъ
сообщение Apr 27 2017, 05:02
Сообщение #6


Знающий
****

Группа: Участник
Сообщений: 758
Регистрация: 27-08-08
Пользователь №: 39 839



Цитата(Baser @ Apr 26 2017, 19:23) *
Феншуем не владею, более того ну вааще не понял синтаксиса и как из первой строки получается вторая, ну да ладно.

Первая это кусочек из makefile, дата передается опцией компоновщику

Цитата
Все таки, чем __DATE__ не нравиться?

Я ж вроде написал. Да и дата это только пример, в реальности много констант генерируются самим компоновщиком.

Цитата
Если генерируете прошивку-релиз, то можно целиком перекомпилировать весь проект, чай не каждые пять минут это делаете, можно и подождать.

Дата+номер сборки дают однозначную информацию о версии. В принципе и номера сборки достаточно, но дата чаще нагляднее - глянул и сразу понятно. Впрочем номер сборки вводится таким же путем - по другому нельзя, т.к. иначе при изменении библиотек или ресурсов можно получить одинаковые номера сборок (номер генерируется автоматически через makefile).

Цитата
А строку в цифру можно перегнать макросами (не мое, тут на форуме как-то пробегало):

Где-то наверное может быть полезным такой подход, но в данном случае это костыли. Вопрос то изначально был не столько о работоспособности (с чем проблем нет), а про красивый (лаконичный и отражающий смысл вкладываемый в него) код соответствующий стандартам С.
Go to the top of the page
 
+Quote Post
jcxz
сообщение May 17 2017, 11:12
Сообщение #7


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(Шаманъ @ Apr 26 2017, 17:43) *
Ну, а что делать с концом секции или с размером, которые определены в скрипте линкера? С точки зрения смысла они указывают в никуда, и для них extern void xxxx самое правильное определение.

Про GCC не знаю, но в IAR конец секции можно так: завести некую переменную (в отдельной секции), а в скрипте линкёра указать расположить эту секцию последней в регионе размещения:
place in RAM_regionA {ro, first block IMAGE_HEAD, last section .codetail};
Насчёт переменных, определённых в скрипте линкёра можно так: положить их определения в отдельный *.h-файл и подключить этот файл к си-исходникам и к скрипту линкёра (линкёр IAR это позволяет).
А с датой (или вообще для общего случая произвольных символов) самое правильное имхо - как указал scifi. Я именно так и делаю.
Go to the top of the page
 
+Quote Post
Шаманъ
сообщение May 18 2017, 14:17
Сообщение #8


Знающий
****

Группа: Участник
Сообщений: 758
Регистрация: 27-08-08
Пользователь №: 39 839



jcxz, тут больше вопрос не в том, как можно - сам знаю не один способ. Вариант с определением символов компоновщика вполне устраивает, просто программа написанная наиболее близко по смыслу не вписывается в стандарт С (хотя GCC все компилирует нормально, немного поругавшись).

Вопрос скорее из серии перфекционизма sm.gif
Go to the top of the page
 
+Quote Post
Baser
сообщение May 18 2017, 17:02
Сообщение #9


Просто Che
*****

Группа: Свой
Сообщений: 1 567
Регистрация: 22-05-07
Из: ExUSSR
Пользователь №: 27 881



Цитата(Шаманъ @ May 18 2017, 17:17) *
Вопрос скорее из серии перфекционизма sm.gif

Я бы сказал, что из серии крайнего перфекционизма.
Мне бы не пришло в голову над такими вещами задумываться, хотя считаюсь педантичным человеком в глазах окружающих sm.gif

Кстати, ИАР на такие конструкции смотрит благосклонно, не выдавая никаких варнингов:

ключ линкера
--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;
А в случае пользовательского символа - пожалуйста, вот и нет предупреждений.
Go to the top of the page
 
+Quote Post
scifi
сообщение May 18 2017, 18:06
Сообщение #10


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Цитата(Шаманъ @ May 18 2017, 17:17) *
Вариант с определением символов компоновщика вполне устраивает, просто программа написанная наиболее близко по смыслу не вписывается в стандарт С (хотя GCC все компилирует нормально, немного поругавшись).

Хочу поставить ЖЫРНУЮ точку.
Значит, пользуемся фичей GCC, а именно определение символа с датой средствами компоновщика. Опять же, в GCC всё работает. Так что ещё тебе надо, любезный? Стандарт Си тут совсем сбоку, поскольку изначально речь идёт о GCC. В других средах другие дела. Короче, дело надо закрыть, так как нет состава преступления. За сим откланяюсь, Ваша Честь.
Go to the top of the page
 
+Quote Post
Шаманъ
сообщение May 18 2017, 18:18
Сообщение #11


Знающий
****

Группа: Участник
Сообщений: 758
Регистрация: 27-08-08
Пользователь №: 39 839



Цитата(Baser @ May 18 2017, 20:02) *
вот и нет предупреждений.

В GCC более ранних версий предупреждений тоже не было, возможно у IAR все еще впереди sm.gif

Цитата(scifi @ May 18 2017, 21:06) *
Так что ещё тебе надо, любезный?

Чтобы компилятор не ругался sm.gif

В реальности он у меня сейчас не ругается, но коряво это выглядит в коде, а когда красиво ругается.

Цитата
Стандарт Си тут совсем сбоку, поскольку изначально речь идёт о GCC.

Нет. Он из-за стандарта ругается, ибо конструкция не по стандарту.
Go to the top of the page
 
+Quote Post
LightElf
сообщение May 19 2017, 09:39
Сообщение #12


Частый гость
**

Группа: Участник
Сообщений: 180
Регистрация: 5-04-09
Пользователь №: 47 205



QUOTE (Шаманъ @ May 18 2017, 21:18) *
Нет. Он из-за стандарта ругается, ибо конструкция не по стандарту.

Тут уж надо определиться. Или по стандарту - и тогда никакой линкерной магии. Или с магией - но тогда не по стандарту.
Go to the top of the page
 
+Quote Post
Шаманъ
сообщение May 19 2017, 12:28
Сообщение #13


Знающий
****

Группа: Участник
Сообщений: 758
Регистрация: 27-08-08
Пользователь №: 39 839



Цитата(LightElf @ May 19 2017, 12:39) *
Или по стандарту - и тогда никакой линкерной магии. Или с магией - но тогда не по стандарту.

Ну да, или с магией, по стандарту, но с кривой программой. Нет гармонии sm.gif
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 18th July 2025 - 15:08
Рейтинг@Mail.ru


Страница сгенерированна за 0.01568 секунд с 7
ELECTRONIX ©2004-2016