|
Чем отличаются выражения ?, Приведения типов |
|
|
|
Oct 27 2005, 02:37
|
Группа: Новичок
Сообщений: 5
Регистрация: 23-06-04
Пользователь №: 143

|
Компилятор WINAVR процессор AVR пример взят из firmware WIZNET
uint size; ulong wr_ptr,rd_ptr ; if(wr_ptr >= rd_ptr) size = wr_ptr - rd_ptr ; else size = 0 - rd_ptr + wr_ptr ;
чем отличаются выражения для size и какова последовательность неявных приведений для этого компилятора ?
|
|
|
|
|
 |
Ответов
|
Oct 27 2005, 09:17
|
Гуру
     
Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882

|
"0 - rd_ptr" эквиавалентно переводу значения rd_ptr в дополнительный код, при сложении с wr_ptr в результате получается операция вычитания. Суть в том, что значение size получается положительным (разность по модулю) в результате любого ветвления. Кстати, обращаю внимание что переменная size здесь имеет тип unsigned int, а переменные rd_ptr и wr_ptr unsigned long. Если бы константой был не 0, который при любой раскладе = 0, то нужно было бы записывать как size = 0L - rd_ptr + wr_ptr ; или size = (ulong)0 - rd_ptr + wr_ptr ; в противном случае операция была бы не с ulong-овскими числами, а с uint-овскими и результат мог быть неверен. Хотя в этом примере видимо предполагается, что значение size не бывает больше, чем 65535.
|
|
|
|
|
Oct 27 2005, 10:43
|

Частый гость
 
Группа: Свой
Сообщений: 112
Регистрация: 15-10-05
Из: Томск
Пользователь №: 9 680

|
Цитата(rezident @ Oct 27 2005, 16:17) "0 - rd_ptr" эквиавалентно переводу значения rd_ptr в дополнительный код, при сложении с wr_ptr в результате получается операция вычитания. Суть в том, что значение size получается положительным (разность по модулю) в результате любого ветвления. size всегда получается >= 0, т.к. объявлен как uint. И результат будет один и тот же при любом ветвлении. Возможно там хотели написать else size = rd_ptr - wr_ptr; Цитата(rezident @ Oct 27 2005, 16:17) Кстати, обращаю внимание что переменная size здесь имеет тип unsigned int, а переменные rd_ptr и wr_ptr unsigned long. Если бы константой был не 0, который при любой раскладе = 0, то нужно было бы записывать как size = 0L - rd_ptr + wr_ptr ; или size = (ulong)0 - rd_ptr + wr_ptr ; в противном случае операция была бы не с ulong-овскими числами, а с uint-овскими и результат мог быть неверен. Хотя в этом примере видимо предполагается, что значение size не бывает больше, чем 65535. Не важно какого типа константа - uint или ulong. Мы ведь результат присваиваем переменной типа uint. Т.е. старшие биты обрежутся, если sizeof(int)<sizeof(long), и останутся неизменными, если равны.
|
|
|
|
|
Oct 27 2005, 10:54
|

Нечётный пользователь.
     
Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417

|
Цитата(starter48 @ Oct 27 2005, 13:43) size всегда получается >= 0, т.к. объявлен как uint. И результат будет один и тот же при любом ветвлении. Возможно там хотели написать else size = rd_ptr - wr_ptr; Нет, там написано именно то, что хотели, просто так хотели (неподумавши). Там циклический буфер размеорм 1/2/4/8К, "указатели" IP - 32-битные, но в буфере может не более его размера, поэтому для размера (в другом месте - для свободного места в буфере) достаточно 16-битной переменной. Для количества принятых данных вычитать всегда надо из указателя головы указатель хвоста и всё. Цитата(starter48 @ Oct 27 2005, 13:43) Не важно какого типа константа - uint или ulong. Мы ведь результат присваиваем переменной типа uint. Т.е. старшие биты обрежутся, если sizeof(int)<sizeof(long), и останутся неизменными, если равны. Полностью поддерживаю. А поскольку размер данных гарантированно влазит в uint - то всё будет нормально. Это тот же момент, что с таймерами и отсечением интервалов. В смысле Код timer_type_t start = get_timer(); while( (timer_type_t)(get_timer() - start) < delay); это абсолютно правильно и не надо никаких Код timer_type_t start = get_timer(); for(;;) { tymer_type_t end = get_timer(); if( end < start ) // и так далее, как у визнета с указателями }
--------------------
Ну, я пошёл… Если что – звоните…
|
|
|
|
|
Oct 27 2005, 11:52
|

Частый гость
 
Группа: Свой
Сообщений: 112
Регистрация: 15-10-05
Из: Томск
Пользователь №: 9 680

|
Цитата(ReAl @ Oct 27 2005, 17:54) Цитата(starter48 @ Oct 27 2005, 13:43) size всегда получается >= 0, т.к. объявлен как uint. И результат будет один и тот же при любом ветвлении. Возможно там хотели написать else size = rd_ptr - wr_ptr; Нет, там написано именно то, что хотели, просто так хотели (неподумавши). Там циклический буфер размеорм 1/2/4/8К, "указатели" IP - 32-битные, но в буфере может не более его размера, поэтому для размера (в другом месте - для свободного места в буфере) достаточно 16-битной переменной. Для количества принятых данных вычитать всегда надо из указателя головы указатель хвоста и всё. Если циклический буфер, то так писать можно при условии, что размер буфера равен макс. числу в перенной size (65536 для 16bit int). Иначе надо писать size = (wr_ptr - rd_ptr) % BUFFER_SIZE; без всяких if. Или, для оригинального варианта, следует заменить 0 на BUFFER_SIZE: Код uint size; ulong wr_ptr,rd_ptr; if(wr_ptr >= rd_ptr) size = wr_ptr - rd_ptr; else size = BUFFER_SIZE - rd_ptr + wr_ptr; консенсус?
|
|
|
|
Сообщений в этой теме
vladsizov Чем отличаются выражения ? Oct 27 2005, 02:37 NickB Ну так это просто арифметика по модулю 65536 в дан... Oct 27 2005, 08:38    vladsizov Цитата(starter48 @ Oct 27 2005, 14:52)Цитата(... Oct 28 2005, 01:02     starter48 Цитата(vladsizov @ Oct 28 2005, 08:02)Цитата(... Oct 28 2005, 10:39      ReAl Цитата(starter48 @ Oct 28 2005, 13:39)Да, есл... Oct 28 2005, 12:04       starter48 Цитата(ReAl @ Oct 28 2005, 19:04)Ещё раз. wr_... Oct 28 2005, 13:02        ReAl Цитата(starter48 @ Oct 28 2005, 16:02)Я понял... Oct 28 2005, 13:38    ReAl Цитата(starter48 @ Oct 27 2005, 14:52)Если ци... Oct 28 2005, 05:13  rezident Цитата(starter48 @ Oct 27 2005, 16:43)Возможн... Oct 27 2005, 13:59 ReAl Цитата(vladsizov @ Oct 27 2005, 05:37)Компиля... Oct 27 2005, 09:27
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|