Вопросы по С/С++ (СИ)
- Eddy_Em
- Собутыльник Кота
- Сообщения: 2516
- Зарегистрирован: Пт июл 12, 2019 22:52:01
- Контактная информация:
Re: Вопросы по С/С++ (СИ)
[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'а может выходить — мало ли какой компилятор попадется... Надежней дефайнами.
Ну так UB же! В общем случае нельзя enum'ом, если значение за пределы enum'а может выходить — мало ли какой компилятор попадется... Надежней дефайнами.
- VladislavS
- Собутыльник Кота
- Сообщения: 2562
- Зарегистрирован: Вт май 01, 2018 19:44:47
Re: Вопросы по С/С++ (СИ)
Надёжней enum class.
- Eddy_Em
- Собутыльник Кота
- Сообщения: 2516
- Зарегистрирован: Пт июл 12, 2019 22:52:01
- Контактная информация:
Re: Вопросы по С/С++ (СИ)
Кресты надежней С? Не надо смешить мои тапочки!
- ПростоНуб
- Собутыльник Кота
- Сообщения: 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: Вопросы по С/С++ (СИ)
[uquote="Eddy_Em",url="/forum/viewtopic.php?p=3711320#p3711320"]Кресты надежней С? Не надо смешить мои тапочки![/uquote]Да ты хоть почитай что это, а потом лужи газируй.
Зачем тут слово typedef? Красивое?
Зачем тут слово typedef? Красивое?
- Eddy_Em
- Собутыльник Кота
- Сообщения: 2516
- Зарегистрирован: Пт июл 12, 2019 22:52:01
- Контактная информация:
Re: Вопросы по С/С++ (СИ)
ПростоНуб, в данном случае - да. Красивое решение. Разве что неудобно, что переменной постоянно нужно еще и поле .direction дописывать... Зато проверка на выход за пределы диапазона автоматом...
VladislavS, сам знаешь, зачем нужен typedef! Не выпендривайся!
VladislavS, сам знаешь, зачем нужен typedef! Не выпендривайся!
Re: Вопросы по С/С++ (СИ)
[uquote="Eddy_Em",url="/forum/viewtopic.php?p=3711320#p3711320"]Кресты надежней С? Не надо смешить мои тапочки![/uquote]
На С можно написать:
И это замечательно работает, на gcc c "-Wall -Wextra" даже предупреждения не выдает. Странно, что тебе это кажется нормой учитывая, что тут якобы есть UB 
На С можно написать:
Код: Выделить всё
typedef enum { north, east, south, west } Dir;
Dir dir = 555;
dir /= 111;
- WiseLord
- Друг Кота
- Сообщения: 4905
- Зарегистрирован: Чт апр 11, 2013 11:19:59
- Откуда: Минск
- Контактная информация:
Re: Вопросы по С/С++ (СИ)
Eddy_Em, для 4 значений (степень двойки) работать будет, для произвольного числа уже нет. Да и битовые поля это не совсем стандарт. Но вообще, да, выглядит красивее, чем деление с остатком.
Reflector, -Werror:
P.S. c -Wextra без -Werror компилирует, но с предупреждениями.
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
Последний раз редактировалось WiseLord Ср окт 02, 2019 11:52:10, всего редактировалось 1 раз.
- VladislavS
- Собутыльник Кота
- Сообщения: 2562
- Зарегистрирован: Вт май 01, 2018 19:44:47
Re: Вопросы по С/С++ (СИ)
Нет, не знаю зачем тут typedef.
Re: Вопросы по С/С++ (СИ)
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"
Что значит "не совсем стандарт"?
Читаем стандарт С11 "6.7.2.1 Structure and union specifiers"
- WiseLord
- Друг Кота
- Сообщения: 4905
- Зарегистрирован: Чт апр 11, 2013 11:19:59
- Откуда: Минск
- Контактная информация:
Re: Вопросы по С/С++ (СИ)
Мне всегда казалось, что для uint8_t (char) битовые поля - это расширение GCC. Возможно, в C11 их для большего числа типов расширили.
- ПростоНуб
- Собутыльник Кота
- Сообщения: 2723
- Зарегистрирован: Пт сен 07, 2018 20:20:02
- Откуда: деревня в Тульской губернии
Re: Вопросы по С/С++ (СИ)
WiseLord, в первом стандарте C, с которым я общался это уже было. Смотрим ISO/IEC 9899: 1990 (С89/C90) на странице 60.
P.S. Помнится, даже у Кернигана и Ритчи битовые поля были )
P.S. Помнится, даже у Кернигана и Ритчи битовые поля были )
- WiseLord
- Друг Кота
- Сообщения: 4905
- Зарегистрирован: Чт апр 11, 2013 11:19:59
- Откуда: Минск
- Контактная информация:
Re: Вопросы по С/С++ (СИ)
Оно просто не для всех типов было. А для тех, которые я юзал (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 лет назад - тоже немало )
В стандарт stdint.h и uint8_t действительно попал только в C99. Но 20 лет назад - тоже немало )
- WiseLord
- Друг Кота
- Сообщения: 4905
- Зарегистрирован: Чт апр 11, 2013 11:19:59
- Откуда: Минск
- Контактная информация:
Re: Вопросы по С/С++ (СИ)
Я не совсем про то. Я про то, что битовые поля стандартны для int и _Bool типов, а вот для однобайтных (char, unsigned char) - это как бы не по стандарту, но работает как расширение gcc.
Re: Вопросы по С/С++ (СИ)
сорри, что исчез - в рабочее время у меня тырнета нет. По пути на работу писал код и столкнулся с проблемой, а так как батарейка была уже на исходе, небыло возможности погуглить, потому на последние капли энергии бросил вопрос сюда.
Но на работе в голове покрутил проблему и... всё не так просто.
Сначала у меня был тип данных dir_t - вправо, влево, вперед, назад. Всё было хорошо. это для робота в лабиринте. Но тут взбрело мне еще выяснить, а где именно я нахожусь. Поэтому придумалось иметь направление. Поэтому и ввёл этот motion_t. И задача выяснить, куда я поеду, если я ехал на север и повернул налево. Но тут я понял, что два разных типа я суммировать не могу, а делать switch/case на каждую комбинацию - можно повеситься. Поэтому я сейчас объединил эти два типа. Т.е.Так что теперь, я их просто суммирую и надо бы еще и обрезать. Причем если эти операции делать отдельно:
всё компилируется без предупреждений, а если сделать хором, как в исходном сообщении - получаю предупреждение о mixed type.
Мммм, как-то на ардуине делал календарь, так там для типа месяца нашел в интернете и сделал так:Но это, возможно, C++ конструкция. И мне унарного инкремента недостаточно.
дефайнами пользоваться не хочу - хочу использовать выразительные средства языка. Компилю Keil uVision.
Но на работе в голове покрутил проблему и... всё не так просто.
Сначала у меня был тип данных 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;Мммм, как-то на ардуине делал календарь, так там для типа месяца нашел в интернете и сделал так:
Код: Выделить всё
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 );
}дефайнами пользоваться не хочу - хочу использовать выразительные средства языка. Компилю 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."
В стандарте же сказано только, что "An implementation may allocate any addressable storage unit large enough to hold a bitfield."
Re: Вопросы по С/С++ (СИ)
[uquote="uldemir",url="/forum/viewtopic.php?p=3711476#p3711476"]Но тут я понял, что два разных типа я суммировать не могу[/uquote]почему нет? C позволяет весьма вольно обращаться с энумами. Вы, случаем, не компилятором C++ свой код собираете?)
[uquote="uldemir",url="/forum/viewtopic.php?p=3711476#p3711476"]Поэтому я сейчас объединил эти два типа.[/uquote]весьма спорное с точки зрения читабельности кода решение. Я бы делал что-то типа того (оно вполне собирается и работает)
[uquote="uldemir",url="/forum/viewtopic.php?p=3711476#p3711476"]Но это, возможно, C++ конструкция[/uquote]да, перегрузка операторов - фича плюсов.
[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;
}Re: Вопросы по С/С++ (СИ)
Собирается, но даёт предупреждение. Мне хочется избежать предупреждений.
Ну, в принципе, да - надо заниматься приведением типов... такое компилируется, почему-то без предупреждений:
Код: Выделить всё
*** 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;
}
А люди посмотрят и скажут: "Собаки летят. Вот и осень."