Ребус с знакобеззнаковыми переменными или когда 208 == -48, а когда и нет
- Войдите на сайт для отправки комментариев
Пнд, 13/11/2017 - 12:58
Бился 3 дня и решил, что возможно кому-то интересно будет.
два массива
char data[8] uint8_t rec_data[8]
Переодически, в коде скетча идет попарное сравнение некоторых элементов массива и начинаются чудеса.
На примере в data[1] содержится B11010000 и в rec_data[1] B11010000, понятно, что интерперитируется это как -48 и 208 соответственно.
Тупое сравнение if (data[1] == rec_data[1]) может давать как истину, так и ложь в разных частях скетча. От чего зависит - непонятно. Причем даже указание явного преобразования ((uint8_t)data[1] == rec_data[1])не помогает! Такое впечатление, что иногда преобразование происходит по битовой маске, а иногда просто тупым отбрасыванием знака.
Может кто, что прояснить по данному вопросу?
В Serial выведите то, что непосредственно сравниваете и увидите, что и с чем сравнивается на самом деле.
Попробуйте еще добавить скобок: (((uint8_t)data[1]) == rec_data[1]). Я не помню приоритета обработки выражений (надо бы поискать и освежить в памяти), а так кто его знает, может (uint8_t) применяется уже к результату (data[1] == rec_data[1]).
upd. Хотя нет, приведение к типу имеет больший приоритет http://ru.cppreference.com/w/cpp/language/operator_precedence
char по умолчанию - знаковый.
char по умолчанию - знаковый.
Это подразумевается в посте как само-собой. Так же как int и long. В чем ценность данной информации для данной проблематики?
В Serial выведите то, что непосредственно сравниваете и увидите, что и с чем сравнивается на самом деле.
Если в Сериал выводить без преобразования типа - отражается один и тот же нечитаемый символ. А если преобразовывать, то ценность вывода в сериал теряется. Так, что данный фокус не прокатывает.
Надо понимать точно логику работы компилятора при сравнении знакового и безнакового числа. Может и то и другое к int преобразовается вообще...
Ну тогда попробуйте принудительно приводить к одному типу не один, а оба сравниваемые параметры ((uint8_t)data[1] == (uint8_t)rec_data[1]).
P.S. В Serial выводите не сам символ, а его код.
Ну тогда попробуйте принудительно приводить к одному типу не один, а оба сравниваемые параметры ((uint8_t)data[1] == (uint8_t)rec_data[1]).
P.S. В Serial выводите не сам символ, а его код.
Да вопрос не в том как победить костылем - я уже сделал. Вопрос в том, из-за чего это происходит. Лично я натыкаюсь на трудновыловимые проблемы неявного преобразования знака/беззнака при операциях сравнения уже второй раз. И каждый раз это страшная боль и часы потерянного времени. Хочется понимать что и как происходит и обходить это, а не засирать код явными преобразованиями где надо и не надо.
Вопрос в том, из-за чего это происходит.
Блин, тема муссируется уже пять часов, ну, Вы,блин, когда-нибудь скетч выложите? Нормальный такой пример, с текстом программы (чем короче, тем лучше) и текстом - что в сериал печатается. Так чтобы видна была проблема. Или так и будем сферического коня в вакууме обсуждать: "Эй мужики, у Sr.FatCat там чего-то не получилось, какие будут версии?"?
Пока нет скетча, вся эта тема
это страшная боль и часы потерянного времени.
Хочется понимать что и как происходит и обходить это, а не засирать код явными преобразованиями где надо и не надо.
А что тут понимать? Ни у компилятора, ни у самого контроллера нет хрустального шара. И программа выполняется так, как Вы ее написали, а не как задумали. ЕвгенийП прав, без скетча мы пока что ведем всего лишь милую беседу и строим гипотезы фактически ни о чем.
Чем вам поможет трехфайловый скетч, если Вы не понимаете сути вопроса? Или как прикажите его уменьшить, чтобы Вы насладились видом четырех if-ов? И как вы собираетесь мне ответить, если не понимаете, что переменну в Serial нельзя запихать "как есть"? Точнее,
что это ничего не дает, потому, что типа char изначально и выводится одним символом, независимо от того, со знаком он или без. А явное преобразование - сразу убивает суть вопроса на корню.
И,vk007, не надо со мной как с дебилом на пальцах и шарах. У меня компилятор и контроллер делают, то что я задумал - именно потому, что я знаю как они работают. Но в С, есть масса нюансов с неявным приведением типов. И "на раз" я не нашел ответ в стандарте. Более того, нет гарантии что GCC впишется по этому вопросу в стандарт. Так, что вопрос у меня имеено для "милой" беседы и обсуждения гипотез, если нет точных ответов на этот вопрос. Просто ответьте мне в каких строках будет "истина", а в каких "ложь"
А если я к описанию переменных добавлю const, а если к параметрам функций?
, если Вы не понимаете сути вопроса?
Просто ответьте мне
Здоров ли ты, брат?
Как же мы ответим, если не понимаем?
Успехов!
Просто ответьте мне в каких строках будет "истина", а в каких "ложь"
8 и 9 строки ложь будет
11-14 истина, потому что в 8 и 9 сравниваются разные типы, а в 11-14 строках идет приведение типа и происходит то что вы назвали "сравнение по маски".
Можете проверить вставив в ваши функции вывод в сериал типа Serial.println(x, DEC);
Чем вам поможет трехфайловый скетч,
Ничем. Его даже читать никто не будет.
Если на маленьких несколькострочных скетчах эффект не проявляется, значит его нет, а есть ошибка в Вашем трёхфайловом скетче. А если проявляется - так покажите.
если Вы не понимаете сути вопроса?
Как же нам понимать, если нам не показывают проблему?
как прикажите его уменьшить,
Никак не прикажу. Проблема у Вас, а не у меня. Я понимаю преобразования типов и вопросов по преобразованию у меня не возникает. Так что хотите - уменьшайте, не хотите - не надо, мне пох.
И как вы собираетесь мне ответить, если не понимаете, что переменну в Serial нельзя запихать "как есть"?
Если Вы не понимаете как вывести переменную "как есть", я мог бы подксказать, но Вам, похоже, это не нужно. Сюда Вы зашли "мило побеседовать".
вопрос у меня имеено для "милой" беседы
Тогда Вы ошиблись форумом. Вот вот сюда.
если нет точных ответов на этот вопрос.
Будут точные вопросы, будут и точные ответы, а "для милой беседы" ... я уже давал ссылку.
Просто ответьте мне в каких строках будет "истина", а в каких "ложь"
Вы решили поиграть в учителя и учеников? Ну-ну ... сами "просто отвечайте" - у меня нет проблем с преобразованием типа. У Вас есть - Вот Вы и отвечайте. Я был готов ответить на конкретный вопрос, если бы Вы снизошли его задать.
А по поводу приведённого текста - сначала синтаксические ошибки исправьте, а то у Вас ни в каких строках ничего не будет, кроме ругани компилятора :)
А если я к описанию переменных добавлю const, а если к параметрам функций?
А если Земля на небесную ось наскочит?
Это и есть милая беседа? :)))
Вообщем жопа из которой растут ноги здесь:
The conversion rank above increases in order bool, signed char, short, int, long, long long. The rank of any unsigned type is equal to the rank of the corresponding signed type. The rank of char is equal to the rank of signed char and unsigned char. The ranks of char16_t, char32_t, and wchar_t are equal to the ranks of their underlying types.
Короче, в ногу себе действительно, мешай знаковые и беззнаковые можно выстрелить отлично. Будьте бдительны!
Ну, слава Богу, вот и мило побеседовали.
Sr.FatCat, знаковые и беззнаковые числа расширяются по-разному.
Чтобы дальнейшая обработка происходила предсказуемо, пользуйтесь масками.
Например:
(myByte & 0x00FF) всегда будет трактоваться как число положительное.