Вопросы по С/С++ (СИ)

Если ваш вопрос не влез ни в одну из вышеперечисленных тем, вам сюда.
Аватара пользователя
Eddy_Em
Собутыльник Кота
Сообщения: 2516
Зарегистрирован: Пт июл 12, 2019 22:52:01
Контактная информация:

Re: Вопросы по С/С++ (СИ)

Сообщение Eddy_Em »

[uquote="VladislavS",url="/forum/viewtopic.php?p=3711253#p3711253"][uquote="Eddy_Em",url="/forum/viewtopic.php?p=3711208#p3711208"]задефайните основные направления,[/uquote]Ну он это и сделал enum-ом.[/uquote]
Ну так UB же! В общем случае нельзя enum'ом, если значение за пределы enum'а может выходить — мало ли какой компилятор попадется... Надежней дефайнами.
Linux rules! Windows must die. Здравомыслящий человек добровольно будет пользоваться мастдаем лишь в двух случаях: под дулом автомата или под влиянием анального зонда.
Я на гитхабе, в ЖЖ
Аватара пользователя
VladislavS
Собутыльник Кота
Сообщения: 2562
Зарегистрирован: Вт май 01, 2018 19:44:47

Re: Вопросы по С/С++ (СИ)

Сообщение VladislavS »

Надёжней enum class.
Аватара пользователя
Eddy_Em
Собутыльник Кота
Сообщения: 2516
Зарегистрирован: Пт июл 12, 2019 22:52:01
Контактная информация:

Re: Вопросы по С/С++ (СИ)

Сообщение Eddy_Em »

Кресты надежней С? Не надо смешить мои тапочки!
Linux rules! Windows must die. Здравомыслящий человек добровольно будет пользоваться мастдаем лишь в двух случаях: под дулом автомата или под влиянием анального зонда.
Я на гитхабе, в ЖЖ
Аватара пользователя
ПростоНуб
Собутыльник Кота
Сообщения: 2723
Зарегистрирован: Пт сен 07, 2018 20:20:02
Откуда: деревня в Тульской губернии

Re: Вопросы по С/С++ (СИ)

Сообщение ПростоНуб »

Eddy_Em, так красивей:

Код: Выделить всё

#define DIRECTION_NORD 0
#define DIRECTION_EAST 1
#define DIRECTION_SOUTH 2
#define DIRECTION_WEST 3

typedef struct directions_st {
  uint8_t direction:2;
} directions_t;

directions_t rotate(directions_t dir, int8_t  angle){
  dir.direction+=angle;
  return dir;
}
или даже без функции

Код: Выделить всё

#define DIRECTION_NORD 0
#define DIRECTION_EAST 1
#define DIRECTION_SOUTH 2
#define DIRECTION_WEST 3

#define DIRECTION_STEP_LEFT(d) d.direction--
#define DIRECTION_STEP_RIGHT(d) d.direction++

typedef struct directions_st {
  uint8_t direction:2;
} directions_t;
Последний раз редактировалось ПростоНуб Ср окт 02, 2019 11:40:21, всего редактировалось 1 раз.
Аватара пользователя
VladislavS
Собутыльник Кота
Сообщения: 2562
Зарегистрирован: Вт май 01, 2018 19:44:47

Re: Вопросы по С/С++ (СИ)

Сообщение VladislavS »

[uquote="Eddy_Em",url="/forum/viewtopic.php?p=3711320#p3711320"]Кресты надежней С? Не надо смешить мои тапочки![/uquote]Да ты хоть почитай что это, а потом лужи газируй.

Зачем тут слово typedef? Красивое?
Аватара пользователя
Eddy_Em
Собутыльник Кота
Сообщения: 2516
Зарегистрирован: Пт июл 12, 2019 22:52:01
Контактная информация:

Re: Вопросы по С/С++ (СИ)

Сообщение Eddy_Em »

ПростоНуб, в данном случае - да. Красивое решение. Разве что неудобно, что переменной постоянно нужно еще и поле .direction дописывать... Зато проверка на выход за пределы диапазона автоматом...
VladislavS, сам знаешь, зачем нужен typedef! Не выпендривайся!
Linux rules! Windows must die. Здравомыслящий человек добровольно будет пользоваться мастдаем лишь в двух случаях: под дулом автомата или под влиянием анального зонда.
Я на гитхабе, в ЖЖ
Reflector
Поставщик валерьянки для Кота
Сообщения: 2089
Зарегистрирован: Вс июн 19, 2016 09:32:03

Re: Вопросы по С/С++ (СИ)

Сообщение Reflector »

[uquote="Eddy_Em",url="/forum/viewtopic.php?p=3711320#p3711320"]Кресты надежней С? Не надо смешить мои тапочки![/uquote]
На С можно написать:

Код: Выделить всё

typedef enum { north, east, south, west } Dir;

Dir dir = 555;
dir /= 111;
И это замечательно работает, на gcc c "-Wall -Wextra" даже предупреждения не выдает. Странно, что тебе это кажется нормой учитывая, что тут якобы есть UB :)
Аватара пользователя
WiseLord
Друг Кота
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск
Контактная информация:

Re: Вопросы по С/С++ (СИ)

Сообщение WiseLord »

Eddy_Em, для 4 значений (степень двойки) работать будет, для произвольного числа уже нет. Да и битовые поля это не совсем стандарт. Но вообще, да, выглядит красивее, чем деление с остатком.

Reflector, -Werror:

Код: Выделить всё

arm-none-eabi-gcc -c -mcpu=cortex-m3 -mthumb   -DUSE_FULL_LL_DRIVER -DSTM32F103xB -D_STM32F1 -D_ILI9341 -D_DISP_SPI -D_DISP_320x240 -D_TDA7439 -D_TDA731X -D_PT232X -D_TDA7418 -D_RDA580X -D_SI470X -D_TEA5767 -Idisplay -Iusb -Idrivers/STM32F1xx_HAL_Driver/Inc -Idrivers/STM32_USB_Device_Library/Core/Inc -Idrivers/CMSIS/Device/ST/STM32F1xx/Include -Idrivers/CMSIS/Include -Isystem -Os -fshort-enums -ffunction-sections -fdata-sections -ffreestanding -Wall -Werror -g -gdwarf-2 -MMD -MP -MT build/main.o -MF build/./main.d -DUSE_FULL_LL_DRIVER -DSTM32F103xB -D_STM32F1 -D_ILI9341 -D_DISP_SPI -D_DISP_320x240 -D_TDA7439 -D_TDA731X -D_PT232X -D_TDA7418 -D_RDA580X -D_SI470X -D_TEA5767 -o build/main.o main.c
main.c: In function 'main':
main.c:112:15: error: unsigned conversion from 'int' to 'Dir' {aka 'enum <anonymous>'} changes value from '555' to '43' [-Werror=overflow]
     Dir dir = 555;
               ^~~
cc1: all warnings being treated as errors
P.S. c -Wextra без -Werror компилирует, но с предупреждениями.
Последний раз редактировалось WiseLord Ср окт 02, 2019 11:52:10, всего редактировалось 1 раз.
Аватара пользователя
VladislavS
Собутыльник Кота
Сообщения: 2562
Зарегистрирован: Вт май 01, 2018 19:44:47

Re: Вопросы по С/С++ (СИ)

Сообщение VladislavS »

Нет, не знаю зачем тут typedef.
Reflector
Поставщик валерьянки для Кота
Сообщения: 2089
Зарегистрирован: Вс июн 19, 2016 09:32:03

Re: Вопросы по С/С++ (СИ)

Сообщение Reflector »

WiseLord, это потому что у тебя задан -fshort-enums, а 555 в байт не влазит, замени на 55, ворнинг пропадет.
Аватара пользователя
ПростоНуб
Собутыльник Кота
Сообщения: 2723
Зарегистрирован: Пт сен 07, 2018 20:20:02
Откуда: деревня в Тульской губернии

Re: Вопросы по С/С++ (СИ)

Сообщение ПростоНуб »

[uquote="WiseLord",url="/forum/viewtopic.php?p=3711331#p3711331"]Да и битовые поля это не совсем стандарт.[/uquote]
Что значит "не совсем стандарт"?
Читаем стандарт С11 "6.7.2.1 Structure and union specifiers"
Аватара пользователя
WiseLord
Друг Кота
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск
Контактная информация:

Re: Вопросы по С/С++ (СИ)

Сообщение WiseLord »

Мне всегда казалось, что для uint8_t (char) битовые поля - это расширение GCC. Возможно, в C11 их для большего числа типов расширили.
Аватара пользователя
ПростоНуб
Собутыльник Кота
Сообщения: 2723
Зарегистрирован: Пт сен 07, 2018 20:20:02
Откуда: деревня в Тульской губернии

Re: Вопросы по С/С++ (СИ)

Сообщение ПростоНуб »

WiseLord, в первом стандарте C, с которым я общался это уже было. Смотрим ISO/IEC 9899: 1990 (С89/C90) на странице 60.

P.S. Помнится, даже у Кернигана и Ритчи битовые поля были )
Аватара пользователя
WiseLord
Друг Кота
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск
Контактная информация:

Re: Вопросы по С/С++ (СИ)

Сообщение WiseLord »

Оно просто не для всех типов было. А для тех, которые я юзал (uint8_t) - подсвечивалось в IDE как расширение gcc (clang-овский статический анализатор в QtCreator)
Аватара пользователя
ПростоНуб
Собутыльник Кота
Сообщения: 2723
Зарегистрирован: Пт сен 07, 2018 20:20:02
Откуда: деревня в Тульской губернии

Re: Вопросы по С/С++ (СИ)

Сообщение ПростоНуб »

WiseLord, uint8_t - определяется в stdint.h как typedef unsigned char uint8_t;
В стандарт stdint.h и uint8_t действительно попал только в C99. Но 20 лет назад - тоже немало )
Аватара пользователя
WiseLord
Друг Кота
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск
Контактная информация:

Re: Вопросы по С/С++ (СИ)

Сообщение WiseLord »

Я не совсем про то. Я про то, что битовые поля стандартны для int и _Bool типов, а вот для однобайтных (char, unsigned char) - это как бы не по стандарту, но работает как расширение gcc.
Аватара пользователя
uldemir
Друг Кота
Сообщения: 7359
Зарегистрирован: Пт авг 28, 2009 21:34:30
Откуда: 845-й км.

Re: Вопросы по С/С++ (СИ)

Сообщение uldemir »

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

Но на работе в голове покрутил проблему и... всё не так просто.

Сначала у меня был тип данных dir_t - вправо, влево, вперед, назад. Всё было хорошо. это для робота в лабиринте. Но тут взбрело мне еще выяснить, а где именно я нахожусь. Поэтому придумалось иметь направление. Поэтому и ввёл этот motion_t. И задача выяснить, куда я поеду, если я ехал на север и повернул налево. Но тут я понял, что два разных типа я суммировать не могу, а делать switch/case на каждую комбинацию - можно повеситься. Поэтому я сейчас объединил эти два типа. Т.е.

Код: Выделить всё

typedef enum {
	straight = 0, 
	right = 1, 
	back = 2, 
	left = 3
} t_dir;
#define	north	straight 
#define	east 	right 
#define	south	back 
#define	west 	left
Так что теперь, я их просто суммирую и надо бы еще и обрезать. Причем если эти операции делать отдельно:

Код: Выделить всё

				move_direction += turn_direction;
				move_direction &= 0x03;
всё компилируется без предупреждений, а если сделать хором, как в исходном сообщении - получаю предупреждение о mixed type.

Мммм, как-то на ардуине делал календарь, так там для типа месяца нашел в интернете и сделал так:

Код: Выделить всё

month_t operator ++( month_t &id, int )
{
   month_t current = id;

   if ( december < id + 1 ) id = january;
   else id = static_cast<month_t>( id + 1 );

   return ( current );
}
Но это, возможно, C++ конструкция. И мне унарного инкремента недостаточно.

дефайнами пользоваться не хочу - хочу использовать выразительные средства языка. Компилю Keil uVision.
А люди посмотрят и скажут: "Собаки летят. Вот и осень."
Аватара пользователя
ПростоНуб
Собутыльник Кота
Сообщения: 2723
Зарегистрирован: Пт сен 07, 2018 20:20:02
Откуда: деревня в Тульской губернии

Re: Вопросы по С/С++ (СИ)

Сообщение ПростоНуб »

WiseLord, тут Вы правы, но, по стандарту, при длине битового поля до 8 бит включительно, результат unsigned char i:2 и unsigned int i:2 - одинаков. Я просто по привычке использовал наиболее короткий тип, как дополнительную защиту от ошибки.
В стандарте же сказано только, что "An implementation may allocate any addressable storage unit large enough to hold a bitfield."
arkhnchul
Друг Кота
Сообщения: 3092
Зарегистрирован: Пн апр 06, 2015 11:01:53
Откуда: москва, уфа

Re: Вопросы по С/С++ (СИ)

Сообщение arkhnchul »

[uquote="uldemir",url="/forum/viewtopic.php?p=3711476#p3711476"]Но тут я понял, что два разных типа я суммировать не могу[/uquote]почему нет? C позволяет весьма вольно обращаться с энумами. Вы, случаем, не компилятором C++ свой код собираете?)
[uquote="uldemir",url="/forum/viewtopic.php?p=3711476#p3711476"]Поэтому я сейчас объединил эти два типа.[/uquote]весьма спорное с точки зрения читабельности кода решение. Я бы делал что-то типа того (оно вполне собирается и работает)
Спойлер

Код: Выделить всё

typedef enum  {
	ROTATION_NONE = 0,
	ROTATION_RIGHT = 1,
	ROTATION_BACKWARD = 2,
	ROTATION_LEFT = 3
} rotation_dir_t;

typedef enum {
	BEARING_NORTH = 0,
	BEARING_EAST = 1,
	BEARING_SOUTH = 2,
	BEARING_WEST = 3
} bearing_dir_t;

bearing_dir_t compute_bearing(bearing_dir_t current_bearing, rotation_dir_t rotation){
	return (bearing_dir_t)(current_bearing + rotation) & 0x03;
}
[uquote="uldemir",url="/forum/viewtopic.php?p=3711476#p3711476"]Но это, возможно, C++ конструкция[/uquote]да, перегрузка операторов - фича плюсов.
Аватара пользователя
uldemir
Друг Кота
Сообщения: 7359
Зарегистрирован: Пт авг 28, 2009 21:34:30
Откуда: 845-й км.

Re: Вопросы по С/С++ (СИ)

Сообщение uldemir »

Собирается, но даёт предупреждение.

Код: Выделить всё

*** Using Compiler 'V5.06 update 6 (build 750)', folder: 'C:\Keil_v5\ARM\ARMCC\Bin'
compiling Maze.c...
Maze.c(57): warning:  #188-D: enumerated type mixed with another type
     return (bearing_dir_t)(current_bearing + rotation) & 0x03;
Maze.c: 1 warning, 0 errors
"Maze.c" - 0 Error(s), 1 Warning(s).
Мне хочется избежать предупреждений.

Ну, в принципе, да - надо заниматься приведением типов... такое компилируется, почему-то без предупреждений:

Код: Выделить всё

bearing_dir_t compute_bearing(bearing_dir_t current_bearing, rotation_dir_t rotation){
	bearing_dir_t next_bearing;
	next_bearing = (bearing_dir_t)(current_bearing + rotation);
	return next_bearing &= 0x03;
}
А люди посмотрят и скажут: "Собаки летят. Вот и осень."
Ответить

Вернуться в «Разные вопросы по МК»