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

Поместить константу float на место int32

Есть структура. Вся структура константная (размещается во флэши). В ней есть 2 поля int.

Дописывал функционал. Ввёл ещё одно поле, которое определяет тип констант. И работаю с ними поразному - или как с int32 или как с float.

А вот при заполнении такой структуры вываливается ошибка.

Как правильно записать, чтобы компилятор понял, что я от него хочу?

typedef const struct
{
  const int32_t            *Index;                // Указатель на редактируемый параметр/ смещение для каналов
  const uint16_t        Ch;                    // 0/ Указатель на канал
  const uint8_t            fSignEn;            // Отображение знака числа
  const uint8_t            LenDig;                // Число цифр в числе (0 - гашение незначащих нулей)
  const uint8_t            DigAfterDot;        // Число цифр после точки (0 - точки нет)
  const uint8_t            DigType;            // Тип результирующего числа (0 - int8, 1 - int16, 2 - int32, 3 - float)
  const int32_t            min,max;            // минимальное и максимальное значение (если <min, то min, если >max, то max)
  const uint16_t        typeEditing;        // возможножность редактирования
  void                    (*savefunc)(void);    // Указатель на функцию записи редактируемых параметров
  const char* const*    NameUnits;            // наименование единиц измерения
} DigEditing_t;

 

//***************************************************************
// @@ 23155. Диаметр трубопровода 1
DigEditing_t dgeD12_1 =                // Меню "Диаметр трубопровода"
{
  0,                                        // непрямое
  offsetof(PipelineChanal_t,QConfChanal[0])+offsetof(QConfChanal_t,dia_D12),    //
  0,                                        // неотображать знак
  7, 3,                                        // 3 знака, нет запятой
  (int32_t)1.0,(int32_t)5.0e3,                // min,max
  3,                                        // float
  PRGEDIT, 0,                                // Редактировать по паролю, не сохранять (сохранять по выходу из PRG)
  &strMm                                    // "мм"
};

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


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

Как правильно записать, чтобы компилятор понял, что я от него хочу?

В gcc делаю так:

//-----------------------------------------------------------------------------
//	typedef struct sPARAM
//-----------------------------------------------------------------------------
typedef struct sPARAM
{
int	delta;
DWORD	act_datetime;

BYTE	park_mask;
BYTE	wait_on;
BYTE	wait_period;
BYTE	pre_on;

BYTE	pre_period;
BYTE	fin_on;
BYTE	fin_period;
BYTE	to_pre;

BYTE	to_fin;
BYTE	to_done;
BYTE	l_pre;
BYTE	l_fin;

BYTE	to_btn_press;
BYTE	to_btn_release;

union
{
	DWORD	flags;
	struct
	{
		union
		{
			WORD	ev_msk;
			struct
			{
				WORD	ev_msk_total:1;
				WORD	ev_msk_restart:1;
				WORD	ev_msk_power_fail:1;
				WORD	ev_msk_enter:1;
				WORD	ev_msk_start:1;
				WORD	ev_msk_release:1;
				WORD	ev_msk_enable:1;
				WORD	ev_msk_disable:1;
				WORD	ev_msk_reserv:8;
			};
		};

		WORD	btn_inv:1;
		WORD	box_led_inv:1;
		WORD	flags_reserv:14;
	};
};

} sPARAM;

//-----------------------------------------------------------------------------
//	const sPARAM param_default
//-----------------------------------------------------------------------------
const sPARAM param_default =
{
delta:			0, // delta
act_datetime:		ACT_ALWAYS,// ACT_NEVER,
park_mask:		0,
wait_on:		RED_TIME(0.2),
wait_period:		RED_TIME(3.0),
pre_on:			RED_TIME(0.2),
pre_period:		RED_TIME(0.5),
fin_on:			RED_TIME(1.0),
fin_period:		RED_TIME(1.0),
to_pre:			TO_TIME(1.0),
to_fin:			TO_TIME(10.0),
to_done:		TO_TIME(2.0),
l_pre:			DISTANCE(1.0),
l_fin:			DISTANCE(0.4),
to_btn_press:		TO_BTN(1.0),
to_btn_release:		TO_BTN(1.0),
ev_msk:			0,
btn_inv:		0,
box_led_inv:		0,
};

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


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

Спасибо. Подумал про union, но немноого не в том ключе. Переклинило чего-то. Как-то я вообще очень редко union применяю.

 

Непроходит.

У меня IAR.

Объявил тип:

typedef union
{
    float    f;
    int32_t    i;
} variant_t;

теперь изменил строчку структуры на

const variant_t min,max; // минимальное и максимальное значение (если <min, то min, если >max, то max)

Работаю соответственно с min.i и min.f. Всё прекрасно (собственно как и было).

При заполнении структуры IAR не даёт указать имя поля (как у Вас). И присваивает все значения как float. хотя я и ставлю L для константы например 200L

 

Как ему указать что из union заполнять?

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


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

есть еще дурацкий вариант сконвертировать float в int руками:

http://www.h-schmidt.net/FloatConverter/

5e3 == 0x459c4000

и еще более дурацкий - сделать такой ковертер на препроцессоре :).

 

по поводу инициализации uniona в IARе: приведение руками к нужному типу вроде должно работать

(int) 0x4444,

(float) 5e-3

 

постфикс L после константы вроде только на длину указывает, а не на тип.

ну то есть

5000L - long int,

5000.0L - double

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


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

Как ему указать что из union заполнять?

Не уверен, но кажется это фича gcc, а не языка C.

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


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

есть еще дурацкий вариант сконвертировать float в int руками

:rolleyes:

Так я так и делал. )) Но хочется, чтобы кто-нибудь потом разобрался ... )) У меня много таких данных. Это менюшка крупного прибора.

 

Приведение сейчас попробую

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


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

по поводу инициализации uniona в IARе: приведение руками к нужному типу вроде должно работать

(int) 0x4444,

(float) 5e-3

Не поможет. int и float легко преобразуются друг в друга С приведением типа. Причем преобразуются правильно - т.е. из целого он сделает плавающее, и наоборот. Т.е. побитовое представление изменится.

 

Что бы оно не менялось, нужно преобразовывать через указатели: как то так - *(int32_t*)(float*)&<ваша константа>. Но для констант это пройти не должно :(

 

Если у вас есть C++ то вас спасет reinterpret_cast<int32_t>(5e-3f) (не забудьте про суффикс f в константе - без него это будет double, и reinterpret_cast не сработает)

 

 

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


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

Не поможет. int и float легко преобразуются друг в друга С приведением типа. Причем преобразуются правильно - т.е. из целого он сделает плавающее, и наоборот. Т.е. побитовое представление изменится.

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

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


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

В QT, кстати, те же проблемы.

Тему не закрываю. Интересно кто и как с такими вопросами борется. Для С++ тоже актуально.

 

Я свою проблему решил.

Я сделал две идентичных структуры. Одну с полями int, вторую с полями float. При обработке поступаю как и прежде.

А при ображении к структуре всё работает.

//***************************************************************
// @@ 15.
MenuItem_t  mnuitSysClock[5] =            // Меню "Настройка часов"/ Пункты меню
{
    {&imCorrClock,                            // Коррекция времени    @@ 151
    0,MenuTimeCorr,0,MenuTimeHlp},
    {&imLocalClock,                            // Местное время        @@ 152
    0,MenuTimeEdit,0,MenuTimeHlp},
    {&imTimeZone,                            // Часовой пояс            @@ 153
    (struct Menu_t *)&dgeTimeZone,EditIntCh,0,TimeZoneHlp},
    {&imSumWin,                                // Летнее/зимнее        @@ 154
    (struct Menu_t *)&rbtSumWin,RadioBtnCh,0,RadioBtnHlp},
    {&imCorrFreq,                            // Коррекция генератора    @@ 155
    (struct Menu_t *)&dgeFreqRtcCorr,EditIntCh,0,EditIntHlp},
};

struct Menu_t mnuSysClock =                // Меню "Настройка часов"
{5,mnuitSysClock};

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


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

это понятно, вопрос был про инициализацию uniona и там вроде как именно по типу должно определяться какое именно поле инициализируется.
Не должно. Стандарт С99, раздел 6.7.8 (Initialization), пункт 17,18:

17.

Each brace-enclosed initializer list has an associated current object. When no

designations are present, subobjects of the current object are initialized in order according

to the type of the current object: array elements in increasing subscript order, structure

members in declaration order, and the first named member of a union.127) In contrast, a

designation causes the following initializer to begin initialization of the subobject

described by the designator. Initialization then continues forward in order, beginning

with the next subobject after that described by the designator.128)

 

18.

Each designator list begins its description with the current object associated with the

closest surrounding brace pair. Each item in the designator list (in order) specifies a

particular member of its current object and changes the current object for the next

designator (if any) to be that member.129) The current object that results at the end of the

designator list is the subobject to be initialized by the following initializer.

Сноски 127,128:

127) If the initializer list for a subaggregate or contained union does not begin with a left brace, its

subobjects are initialized as usual, but the subaggregate or contained union does not become the

current object: current objects are associated only with brace-enclosed initializer lists.

128) After a union member is initialized, the next object is not the next member of the union; instead, it is

the next subobject of an object containing the union.

Так что увы, тип константы полностью игнорируется.

 

Но в том же С99 есть синтаксис инициализации с указанием конкретного поля (a-la GCC, но немного по другому)

initializer:
assignment-expression
{ initializer-list }
{ initializer-list , }

initializer-list:
designationopt initializer
initializer-list , designationopt initializer

designation:
designator-list =

designator-list:
designator
designator-list designator

designator:
[ constant-expression ]
. identifier

 

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


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

2 XVR. :beer:

Проверил - работает. :biggrin:

Правда только для union можно указать.

:a14:

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


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

Однозначно только union.

Для доступа к полям union можно применять конструкции вида:

struct { int x, y, z; } point = { .y=10, .z=20, .x=30 };

 

(стандарт с99, в c++ работать не будет).

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


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

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

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

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

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

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

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

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

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

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