Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Программная инженерия > Микроконтроллеры, робототехника, схемотехника, 3D принтеры
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 16.04.2018, 13:39   #1
avd
Пользователь
 
Регистрация: 06.06.2010
Сообщений: 79
По умолчанию Сравнение знаковых и беззнаковых значений

Здравствуйте.
IDE Atmel Studio 7.
Я понимаю, что лучше не сравнивать знаковые и беззнаковые значения.
Но всё же ...

Код:
  volatile int8_t a; 
  volatile uint8_t b;	
	
  a = 5; b = 7;
	
  if ((a - b) > 1)
  {
    .....
  }
Если переменные однобайтные - условие не выполняется.
Если двухбайтные (int16_t и uint16_t) - выполняется.

Боюсь заработаю гексакосиойгексеконтагексафобию.

Последний раз редактировалось avd; 16.04.2018 в 15:19.
avd вне форума Ответить с цитированием
Старый 16.04.2018, 16:41   #2
Alter
Старожил
 
Аватар для Alter
 
Регистрация: 06.08.2007
Сообщений: 2,239
По умолчанию

createlink.gif Вот тут написано почему так не надо
Цитата:
ПРАВИЛО #8 – Целые числа со знаком и без
Целые числа со знаком не должны сочетаться с целыми числами без знаков в сравнениях или выражениях. Десятичные константы, не подразумевающие наличие знаков, должны быть описаны с 'u' на конце.

Код:
// Так делать нельзя...
uint8_t  a = 6u;
int8_t   b = -9;

if (a + b < 4)
{
   // если бы -9 + 6 было -3 < 4 как ожидалось.
   // была бы выполнена эта ветвь
}
else
{
   //но поскольку -9 + 6 это  (0x100 - 9) + 6 = 253
   //то будет выполнена эта ветвь
}
Аргументация: Некоторые детали управления целочисленными данными со знаком зависят от реализации (то есть от от конкретного компилятора). Кроме того, в результате смешивания знаковых и беззнаковых данных могут возникать информационно-зависимые ошибки.

Последний раз редактировалось Alter; 16.04.2018 в 17:23.
Alter вне форума Ответить с цитированием
Старый 16.04.2018, 16:56   #3
avd
Пользователь
 
Регистрация: 06.06.2010
Сообщений: 79
По умолчанию

Alter, спасибо.
Но почему программа выполняется по разному с однобайтными и двухбайтными числами?
avd вне форума Ответить с цитированием
Старый 16.04.2018, 17:04   #4
Аватар
Старожил
 
Аватар для Аватар
 
Регистрация: 17.11.2010
Сообщений: 19,042
По умолчанию

Если результат вычитания трактуется как беззнаковый, то больше 1, если знаковый то меньше. И как там еще компилятор с единицей сравнивает. Это у разрабов компилятора нужно спрашивать ))
Если бы архитекторы строили здания так, как программисты пишут программы, то первый залетевший дятел разрушил бы цивилизацию
Аватар вне форума Ответить с цитированием
Старый 16.04.2018, 18:12   #5
Alter
Старожил
 
Аватар для Alter
 
Регистрация: 06.08.2007
Сообщений: 2,239
По умолчанию

Возможно это:
Сравнение знаковых и беззнаковых чисел - C++
Цитата:
16.12.2011, 22:22 #2
Ну, здесь производится арифметическое преобразование типов, согласно которому операнд "меньшего" типа приводится к типу операнда "большего" типа. В иерархии типов "большим" считается тот тип, который может представить большее положительное значение.
О размерности данных в программах для микроконтроллеров

Типы описаны в stdint.h
Например: C:\Program Files\Arduino\hardware\tools\avr\av r\include\stdint.h

Нескольно простых вопросов о программировании AVR на Си.
Цитата:
ptr128 Сб дек 24, 2016 19:39:08
С точки зрения подавляющего большинства CPU (предположу даже, что всех современных) и AVR в том числе, целые числа в памяти вообще не разделяются на знаковые или беззнаковые. С точки зрения CPU и uint8_t и int8_t - одно и тоже. Просто байт. Восемь бит.
Однако для работы со знаковыми и безнаковыми числами существуют различные машинные команды. Беззнаковые команды оперируют целиком с 8 битами. А вот знаковые анализируют самый старший бит. Если этот бит нулевой - число не отрицательное (положительное или ноль). Еcли единица - то отрицательное. Причем отрицательное в дополнительном коде.
То есть, значения от 0 до 127 будут считаться знаковой командой положительными. А вот уже беззнаковое 128 будет считаться знаковым -128. Беззнаковое 255 будет считаться знаковой -1.
Иными словами сравнивая два байта, содержащие значения 200 и 100, как беззнаковые числа, Вы получите, что первое больше второго. Сравнивая эти же два байта, как знаковые числа, результат будет противоположным - первое меньше второго.
Чуть не забыл. Сравнить знаковое число с беззнаковым у Вас вообще не получится по той простой причине, что если в выражении компилятор встречает знаковое и беззнаковое число, то знаковое будет преобразовано в беззнаковое. То есть сравнение знакового числа с беззнаковым всегда эквивалентно сравнению беззнаковых чисел.
_
Вот эксперимент на ARDUINO 1.8.5, Arduino Nano 3.0 (ATmega328):
Код:
void setup() {

  Serial.begin(9600);
///////////////////////////////////
  Serial.println("volatile int8_t a; volatile uint8_t b;");
  volatile int8_t a; 
  volatile uint8_t b; 
  volatile uint8_t cuint8t; 
  volatile int8_t cint8t;   

  a = 5; b = 7;

  Serial.print("SizeOf(a) = "); Serial.print(sizeof(a)); Serial.print("; a="); Serial.print(a); Serial.println(";");
  Serial.print("SizeOf(b) = "); Serial.print(sizeof(b)); Serial.print("; b="); Serial.print(b); Serial.println(";"); 
   cuint8t = a - b;
   cint8t  = a - b;
  Serial.print("volatile uint8_t cuint8t: a - b = "); Serial.println(cuint8t);
  Serial.print("volatile int8_t cint8t: a - b = "); Serial.println(cint8t);
  Serial.println(" ");
  Serial.print("a - b = "); Serial.println(a - b);
  
  if ((a - b) > 1)
  {
    Serial.println("Result: (a - b) > 1");
  }
   else
  {
    Serial.println("Result: (a - b) < 1");
  }
  Serial.println("_________________________________________________________");
  Serial.println(" ");
///////////////////////////////////
  Serial.println("volatile int16_t a2; volatile uint16_t b2;");
  volatile int16_t a2; 
  volatile uint16_t b2; 
  volatile uint16_t c2uint16t; 
  volatile int16_t c2int16t;  

  a2 = 5; b2 = 7;

  Serial.print("SizeOf(a2) = "); Serial.print(sizeof(a2)); Serial.print("; a2="); Serial.print(a2); Serial.println(";");
  Serial.print("SizeOf(b2) = "); Serial.print(sizeof(b2)); Serial.print("; b2="); Serial.print(b2); Serial.println(";"); 
   c2uint16t = a2 - b2;
   c2int16t  = a2 - b2;
  Serial.print("volatile uint16_t c2uint16t: a2 - b2 = "); Serial.println(c2uint16t);
  Serial.print("volatile int16_t c2int16t: a2 - b2 = "); Serial.println(c2int16t);
  Serial.println(" ");
  Serial.print("a2 - b2 = "); Serial.println(a2 - b2);
  
  if ((a2 - b2) > 1)
  {
    Serial.println("Result: (a2 - b2) > 1");
  }
   else
  {
    Serial.println("Result: (a2 - b2) < 1");
  }
  Serial.println(" ");
  Serial.println(" ");  
///////////////////////////////////  
}

void loop() {

}
Результат:
Цитата:
volatile int8_t a; volatile uint8_t b;
SizeOf(a) = 1; a=5;
SizeOf(b) = 1; b=7;
volatile uint8_t cuint8t: a - b = 254
volatile int8_t cint8t: a - b = -2

a - b = -2
Result: (a - b) < 1
___________________________________ ______________________

volatile int16_t a2; volatile uint16_t b2;
SizeOf(a2) = 2; a2=5;
SizeOf(b2) = 2; b2=7;
volatile uint16_t c2uint16t: a2 - b2 = 65534
volatile int16_t c2int16t: a2 - b2 = -2

a2 - b2 = 65534
Result: (a2 - b2) > 1

Последний раз редактировалось Alter; 16.04.2018 в 19:38.
Alter вне форума Ответить с цитированием
Старый 16.04.2018, 20:09   #6
avd
Пользователь
 
Регистрация: 06.06.2010
Сообщений: 79
По умолчанию

Благодарю.
Торжественно обещаю больше не сравнивать знаковые и беззнаковые величины.
avd вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Сравнение знаковых чисел Herly Assembler - Ассемблер (FASM, MASM, WASM, NASM, GoASM, Gas, RosAsm, HLA) и не рекомендуем TASM 5 12.06.2013 00:31
Сравнение значений vajtek Общие вопросы Delphi 2 23.08.2011 19:53
Сравнение значений в 2х столбцах и удаление лишних значений.. Tyr Microsoft Office Excel 2 16.12.2010 18:19
вычисление для знаковых и беззнаковых целых чисел!!!! senna_ololo Assembler - Ассемблер (FASM, MASM, WASM, NASM, GoASM, Gas, RosAsm, HLA) и не рекомендуем TASM 1 07.06.2010 23:38
Вычисление для знаковых и без знаковых целых чисел в asm. kup9 Assembler - Ассемблер (FASM, MASM, WASM, NASM, GoASM, Gas, RosAsm, HLA) и не рекомендуем TASM 2 06.06.2010 18:21