Вопросы по С/С++ (СИ)
- Сообщения: 2567
- Зарегистрирован: Вт май 01, 2018 19:44:47
- Реклама
- Сообщения: 2089
- Зарегистрирован: Вс июн 19, 2016 09:32:03
WiseLord, это потому что у тебя задан -fshort-enums, а 555 в байт не влазит, замени на 55, ворнинг пропадет.
[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"
Мне всегда казалось, что для uint8_t (char) битовые поля - это расширение GCC. Возможно, в C11 их для большего числа типов расширили.
WiseLord, в первом стандарте C, с которым я общался это уже было. Смотрим ISO/IEC 9899: 1990 (С89/C90) на странице 60.
P.S. Помнится, даже у Кернигана и Ритчи битовые поля были )
P.S. Помнится, даже у Кернигана и Ритчи битовые поля были )
- Реклама
Оно просто не для всех типов было. А для тех, которые я юзал (uint8_t) - подсвечивалось в IDE как расширение gcc (clang-овский статический анализатор в QtCreator)
WiseLord, uint8_t - определяется в stdint.h как typedef unsigned char uint8_t;
В стандарт stdint.h и uint8_t действительно попал только в C99. Но 20 лет назад - тоже немало )
В стандарт stdint.h и uint8_t действительно попал только в C99. Но 20 лет назад - тоже немало )
Я не совсем про то. Я про то, что битовые поля стандартны для int и _Bool типов, а вот для однобайтных (char, unsigned char) - это как бы не по стандарту, но работает как расширение gcc.
сорри, что исчез - в рабочее время у меня тырнета нет. По пути на работу писал код и столкнулся с проблемой, а так как батарейка была уже на исходе, небыло возможности погуглить, потому на последние капли энергии бросил вопрос сюда.
Но на работе в голове покрутил проблему и... всё не так просто.
Сначала у меня был тип данных 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.
А люди посмотрят и скажут: "Собаки летят. Вот и осень."
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."
[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;
}Собирается, но даёт предупреждение. Мне хочется избежать предупреждений.
Ну, в принципе, да - надо заниматься приведением типов... такое компилируется, почему-то без предупреждений:
Код: Выделить всё
*** 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;
}
А люди посмотрят и скажут: "Собаки летят. Вот и осень."
имхо: избавляться от варнингов нет необходимости, если они на самом деле являются следствием реализации алгоритма. варнинг говорит о том, что мнение компилятора и программиста по данному вопросу МОГУТ расходиться, но не факт, что это представляет проблему. приведение типа в данном случае является страусиной политикой: не вижу, значит, это не существует. а это заведомо хуже, чем вижу, но не боюсь, ибо...
то же самое с битовыми полями. я вижу в этом большой минус: отсутствие явного маскирования искажает алгоритм работы, и вводит в заблуждение. если алгоритм не просматривается по коду - это, с моей точки зрения, плохо.
для полностью "прозрачной" реализации я бы сделал как-то так:
то же самое с битовыми полями. я вижу в этом большой минус: отсутствие явного маскирования искажает алгоритм работы, и вводит в заблуждение. если алгоритм не просматривается по коду - это, с моей точки зрения, плохо.
для полностью "прозрачной" реализации я бы сделал как-то так:
Код: Выделить всё
typedef enum{
DIR_FIRST,
// добавлять ниже, но не выше!
DIR_NORD,
DIR_EAST,
DIR_SOUTH,
DIR_WEST,
// ниже не добавлять!
DIR_LAST
} direction_t;
direction_t rotate_right(direction_t current_dir){
if(++current_dir >= DIR_LAST) current_dir = DIR_FIRST + 1;
return current_dir;
}
direction_t rotate_left(direction_t current_dir){
if(--current_dir == DIR_FIRST) current_dir = DIR_LAST - 1;
return current_dir;если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
- Сообщения: 1842
- Зарегистрирован: Вт авг 15, 2017 10:51:13
[uquote="ARV",url="/forum/viewtopic.php?p=3711791#p3711791"]имхо: избавляться от варнингов нет необходимости, если они на самом деле являются следствием реализации алгоритма. варнинг говорит о том, что мнение компилятора и программиста по данному вопросу МОГУТ расходиться, но не факт, что это представляет проблему. приведение типа в данном случае является страусиной политикой: не вижу, значит, это не существует. а это заведомо хуже, чем вижу, но не боюсь, ибо...[/uquote]
В корне неправильно!
От варнингов нужно избавляться всегда. Если Ваше мнение расходится с мнением компилятора хуже будет только вам. Потому что компилятор сделает по-своему. Он вас предупредил, Вы проигнорили - дальше виноваты сами за последствия.
Если на вас едет паровоз, машинист видит вас и предупреждает гудком чтобы Вы ушли с рельс. Если вы это проигнорите - паровозу от этого не поплохеет. Ну разве что скотоотбойник запачкает
А как именно избавляться - это уже можно делать по-разному.
В корне неправильно!
От варнингов нужно избавляться всегда. Если Ваше мнение расходится с мнением компилятора хуже будет только вам. Потому что компилятор сделает по-своему. Он вас предупредил, Вы проигнорили - дальше виноваты сами за последствия.
Если на вас едет паровоз, машинист видит вас и предупреждает гудком чтобы Вы ушли с рельс. Если вы это проигнорите - паровозу от этого не поплохеет. Ну разве что скотоотбойник запачкает
А как именно избавляться - это уже можно делать по-разному.
jcxz, тут я с Вами не согласен. Простейший пример. Имеем таблицу указателей на функции. Пусть у функции один параметр. Причем части функций этот параметр просто не нужен, хотя остальные функции без него обойтись не могут. Получаем два варианта решения:
1. Игнорируем конкретное предупреждение о неиспольуемом значении параметра:
2. Усложняем алгоритм, разбивая таблицу на две и выполняя поиск нужного обработчика в обоих таблицах.
Пример:
Здесь обработчками ir_handler_pgm_prev(), ir_handler_pgm_next() и ir_handler_switch_channel() код нажатой кнопки на ИК пульте совершенно не нужен, тогда как обработчиками ir_handler_brightness() и ir_handler_pgm_no() он необходим.
1. Игнорируем конкретное предупреждение о неиспольуемом значении параметра:
Код: Выделить всё
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
...
#pragma GCC diagnostic pop
Пример:
Код: Выделить всё
typedef struct ir_cmd_st {
uint8_t code;
uint8_t (*ir_handler)(uint8_t);
} ir_cmd_t;
static ir_cmd_t ir_cmd_table[] = {
{ IR_NEC_CMD_UP, ir_handler_brightness },
{ IR_NEC_CMD_DOWN, ir_handler_brightness },
{ IR_NEC_CMD_LEFT, ir_handler_pgm_prev},
{ IR_NEC_CMD_RIGHT, ir_handler_pgm_next},
{ IR_NEC_CMD_OK, ir_handler_switch_channel},
{ IR_NEC_CMD_0, ir_handler_pgm_no},
{ IR_NEC_CMD_1, ir_handler_pgm_no},
{ IR_NEC_CMD_2, ir_handler_pgm_no},
{ IR_NEC_CMD_3, ir_handler_pgm_no},
{ IR_NEC_CMD_4, ir_handler_pgm_no},
{ IR_NEC_CMD_5, ir_handler_pgm_no},
{ IR_NEC_CMD_6, ir_handler_pgm_no},
{ IR_NEC_CMD_7, ir_handler_pgm_no},
{ IR_NEC_CMD_8, ir_handler_pgm_no},
{ IR_NEC_CMD_9, ir_handler_pgm_no} };
Не знаю, насколько кошерно было моё решение, но я в подобном случае обьявлял статическую переменную с параметром команды. Или в моём случае статическую структуру с несколькими параметрами. Так я избавился от неоднозначности вызова.
GARMIN, например, на SDCС и STM8S, для которого был использован данный код, Ваш подход приведет к дополнительным машинным командам в каждом обработчике, которому нужен код клавиши. Тогда как в моем случае, код клавиши сразу оказывается в аккумуляторе, где он и был в вызывающей программе при поиске обработчика в таблице. Мне даже в память этот код не нужно сохранять.
К тому же, это простейший пример. А бывают таблицы куда более сложных обработчиков. При этом, если у меня выбор между лишней pragma и потреблением дополнительной памяти в статическом сегменте SRAM, я выберу первое )
К тому же, это простейший пример. А бывают таблицы куда более сложных обработчиков. При этом, если у меня выбор между лишней pragma и потреблением дополнительной памяти в статическом сегменте SRAM, я выберу первое )
- Сообщения: 2567
- Зарегистрирован: Вт май 01, 2018 19:44:47
ПростоНуб, вызываешь с параметром функцию без параметров? И эти люди запрещают мне перегрузку 
- Сообщения: 2516
- Зарегистрирован: Пт июл 12, 2019 22:52:01
Убрал.
Нарушение Правил форума п. 2.3
aen
Нарушение Правил форума п. 2.3
aen
VladislavS, Вы как всегда не в теме )))
В массиве указателей на функцию все функции должны быть с одинаковым возвращаемым значением и с одинаковым набором параметров. Поэтому, если каким-то из этих функций нужен для алгоритма параметр, то его приходится передавать всем функциям в этом массиве.
То есть, тут и близко не пахнет перегрузкой. Это разные функции выполняющие разные действия при возникновении подобных событий. В данном случае - нажатии разных кнопок на одном и том же пульте ДУ на ИК лучах.
В массиве указателей на функцию все функции должны быть с одинаковым возвращаемым значением и с одинаковым набором параметров. Поэтому, если каким-то из этих функций нужен для алгоритма параметр, то его приходится передавать всем функциям в этом массиве.
То есть, тут и близко не пахнет перегрузкой. Это разные функции выполняющие разные действия при возникновении подобных событий. В данном случае - нажатии разных кнопок на одном и том же пульте ДУ на ИК лучах.


