Перейти к содержанию
    

Результирующий тип выражений в Си

Приветствую!

Допустим, есть функция

static u32 HexToInt1(u8 Symb)
{
  if(Symb <= '9') return Symb - '0';
  else return (Symb & 0x7) + 9;
}

 

Есть правила, по которым сохраняются или неявно преобразуются типы представления переменных.

1. В условии if(Symb <= '9') тип выражения будет int, потому что '9' имеет этот тип, а все возможные значения u8 "влазят" в диапазон представления положительных значений int.

2. В операторе return Symb - '0' тип выражения будет int. Однако функция возвращает u32. Будет ли здесь иметь место какое-либо неявное преобразование?

3. Какой тип будут иметь выражения (Symb & 0x7) + 9 и return (Symb & 0x7) + 9?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

36 минут назад, Arlleex сказал:

1. В условии if(Symb <= '9') тип выражения будет int, потому что '9' имеет этот тип, а все возможные значения u8 "влазят" в диапазон представления положительных значений int.

Нет, не поэтому.

ISO/IEC 9899, параграф 6.5.8

Цитата

Each of the operators < (less than), > (greater than), <= (less than or equal to), and >=
(greater than or equal to) shall yield 1 if the specified relation is true and 0 if it is false.
The result has type int.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 минуту назад, andrew_b сказал:

Нет, не поэтому.

ISO/IEC 9899, параграф 6.5.8

Ну да. Но, все-таки, Symb будет рассматриваться как int, так?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

3 часа назад, Arlleex сказал:

1. В условии if(Symb <= '9') тип выражения будет int, потому что '9' имеет этот тип

Имхо '9' имеет тип char.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

3 часа назад, Arlleex сказал:

Допустим, есть функция


static u32 HexToInt1(u8 Symb)
{
  if(Symb <= '9') return Symb - '0';
  else return (Symb & 0x7) + 9;
}

 

Имхо оптимальнее так:

static u32 HexToInt1(u8 Symb)
{
  uint i;
  if ((i = Symb - '0') > 9) i = i - 'A' + '0' & 7;
  return i;
}

:wink2:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

13 минут назад, jcxz сказал:

Имхо оптимальнее так:


static u32 HexToInt1(u8 Symb)
{
  uint i;
  if ((i = Symb - '0') > 9) i = i - 'A' + '0' & 7;
  return i;
}

 

Неа, подаю символ 'F' на вход, получаю 5 =)

 

Моя функция в исходном виде выше была предназначена для преобразования ASCII HEX-тетрады в двоичный вид.

Причем, на вход подаются только символы '0'-'9', 'a'-'f' или 'A'-'F'. Однако, сейчас в голову стукнуло, что я пишу парсер протокола, в котором, на самом деле, все может быть...

В итоге написал так

static u32 HexToInt1(u32 Symb, u32 *IntBuf)
{
  if(Symb >= '0' && Symb <= '9') {*IntBuf = Symb - '0'; return 0;}
  if((Symb >= 'a' && Symb <= 'f') || (Symb >= 'A' && Symb <= 'F'))
  {*IntBuf = (Symb & 0x7) + 9; return 0;} return 1;
}

 

В случае, если встретится запрещенный символ - функция вернет 1, иначе - 0, при этом записав адекватное преобразование в *IntBuf.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

49 minutes ago, jcxz said:

Имхо '9' имеет тип char.

In C, character literals such as 'a' have type int

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

3 часа назад, Arlleex сказал:

Неа, подаю символ 'F' на вход, получаю 5 =)

Ну да - там ещё 10 надо было прибавить.  ;)

Цитата

Моя функция в исходном виде выше была предназначена для преобразования ASCII HEX-тетрады в двоичный вид.

Причем, на вход подаются только символы '0'-'9', 'a'-'f' или 'A'-'F'. Однако, сейчас в голову стукнуло, что я пишу парсер протокола, в котором, на самом деле, все может быть...

А я думал - у Вас точка вызова гарантирует, что символы только из допустимого диапазона. Я заключил это из кода функции, даже не подумал что Вы об этом не подумали... :acute:

Цитата

В итоге написал так


static u32 HexToInt1(u32 Symb, u32 *IntBuf)
{
  if(Symb >= '0' && Symb <= '9') {*IntBuf = Symb - '0'; return 0;}
  if((Symb >= 'a' && Symb <= 'f') || (Symb >= 'A' && Symb <= 'F'))
  {*IntBuf = (Symb & 0x7) + 9; return 0;} return 1;
}

В случае, если встретится запрещенный символ - функция вернет 1, иначе - 0, при этом записав адекватное преобразование в *IntBuf.

Очень громоздко! Одних только ветвлений 6 штук! Если для ручного ввода ещё как-то пойдёт, то для парсинга протокола я не стал бы так делать.

Сравните:

static int HexToInt1(u8 Symb)
{
  uint i;
  if ((i = Symb - '0') > 9) {
    i = (i & ~0x20) - 0x11;
    if (i > 5) return -1;
    i += 10;
  }  
  return i;
}

Всего 2 ветвления. Сравните листинги.  :wink2:

Да и аргумент лучше переделать на uint Symb.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 час назад, jcxz сказал:

Всего 2 ветвления. Сравните листинги...

Не понимаю, как Вы это делаете:good2: Шо то я сидел сидел, да не придумал, потому в лоб и накатал... Спасибо, оно работает!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

19 минут назад, Arlleex сказал:

Не понимаю, как Вы это делаете:good2: 

Надо думать как процессор.  :bad:

:biggrin:

19 минут назад, Arlleex сказал:

Шо то я сидел сидел, да не придумал, потому в лоб и накатал... Спасибо, оно работает!

Да пожалуйста. Пользуйтесь на здоровье  :yes3:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Последнее сложение можно сократить:

static int HexToInt1(u8 Symb)
{
  uint i;
  if ((i = Symb - '0') > 9) {
    i = (i & ~0x20) - 7;
    if (i > 15) return -1;
  }  
  return i;
}

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

18 минут назад, ae_ сказал:

Последнее сложение можно сократить...

Я, в общем-то, сразу так и сделал, к тому же избавился от лишней переменной i

static s32 HexToInt1(u32 Symb)
{
  if((Symb = Symb - '0') > 9)
  {
    Symb = (Symb & ~0x20) - 7;
    if(Symb > 15) return -1;
  }
  return Symb;
}

:wink:

Изменено пользователем Arlleex

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

6 часов назад, ae_ сказал:

Последнее сложение можно сократить:

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

5 часов назад, Arlleex сказал:

Я, в общем-то, сразу так и сделал, к тому же избавился от лишней переменной i

И зря. Добавили баг. Там нет лишних операций. Сначала подумайте почему именно такие операции, прежде чем что-то сокращать.

А переменная та же или отдельная - это дело вкуса. На код это никак не повлияет. Повлиять может только замена u8 на u32 (или uint) - это полезно.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

56 минут назад, jcxz сказал:

И зря. Добавили баг. Там нет лишних операций. Сначала подумайте почему именно такие операции, прежде чем что-то сокращать.

Ваша правда, баг на ровном месте... Действительно поспешная корректировка. Верну назад.

Благодарю за бдительность:blush:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...