реклама на сайте
подробности

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> >>, Что означает эта запись?
niktagor
сообщение Jul 1 2009, 16:01
Сообщение #1


Участник
*

Группа: Участник
Сообщений: 29
Регистрация: 24-06-09
Пользователь №: 50 601



Братцы, я с языком си знаком слабовато. Что означает вот эта запись? Подскажите пожалуйста.

*pDMA_DBP = (unsigned short)((unsigned int)sSPORT0_TX_Descriptor >> 16);
Go to the top of the page
 
+Quote Post
rezident
сообщение Jul 1 2009, 16:59
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Переменная sSPORT0_TX_Descriptor приводится к типу unsigned int.
Над ее содержимым производится арифметический сдвиг вправо (в сторону младшего бита) на 16 бит.
Результат сдвига приводится к типу unsigned short и записывается по адресу, который содержит переменная указателя pDMA_DB.
Go to the top of the page
 
+Quote Post
defunct
сообщение Jul 1 2009, 23:42
Сообщение #3


кекс
******

Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326



>> - обозначает сдвиг вправо.

x >> n
сдвиг переменной x вправо на n разрядов.

пример:
1100 >> 1 = 0110

Цитата
арифметический сдвиг вправо

Всегда думал что над (unsigned int) может производиться только строго логический сдвиг. Арифметический же должен выполняться исключительно над (signed) переменными.

собсно не сложно в этом убедиться:

signed int x1 = 0x80000000;
unsigned int x2 = 0x80000000;

printf("x1 >> 3 = 0x%x\nx2 >> 3 = 0x%x", x1 >> 3, x2 >> 3);

результат:
x1 >> 3 = 0xF0000000 - арифметический сдвиг
x2 >> 3 = 0x10000000 - логический сдвиг
Go to the top of the page
 
+Quote Post
DpInRock
сообщение Jul 2 2009, 02:16
Сообщение #4


Гуру
******

Группа: Участник
Сообщений: 2 254
Регистрация: 4-05-07
Из: Moscow
Пользователь №: 27 515



>> в Сях - это деление на степень двойки. Вот так проще всего описать.
Скажем, -4 сдвинуть вправо будет -2.
4 сдвинуть вправо будет 2.
(А побитнно если рассматривать эти числа будет очень существенная разница. Команда арифметического сдвига дублирует при сдвиге старший бит. И компилятор сам решает какую команду применить).

Посему, если работаем с битами, масками, управляющими словами, адресами регистров - не надо использовать ЗНАКОВЫЕ объявления.
Вернее, использвать можно, но только ТОЧНО зная, что делаешь и зачем тебе это нужно.

У меня вот такое правило. Переменные объявляю всегда unsigned. Если уж объявляю signed - то уж с конкретной явной целью. К примеру буду вычислять что=нибудь, что имеет знак, или потребуется сравнивать что-то с чем-то и потребуется значение разницы.

Короче, куда ни кинь - кругом надо всегда иметь ввиду знаковость переменной.

Сообщение отредактировал DpInRock - Jul 2 2009, 02:50


--------------------
On the road again (Canned Heat)
Go to the top of the page
 
+Quote Post
niktagor
сообщение Jul 2 2009, 07:51
Сообщение #5


Участник
*

Группа: Участник
Сообщений: 29
Регистрация: 24-06-09
Пользователь №: 50 601



Спасибо, все понял! biggrin.gif
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Jul 2 2009, 09:20
Сообщение #6


неотягощённый злом
******

Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643



То, что понял - это хорошо! Но очень полезно САМОМУ отыскивать информацию. И Википедия очень часто в этом деле помогает. Ну а Гугл - почти наверняка...
Почитай: WIKI-Битовый сдвиг


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
rezident
сообщение Jul 2 2009, 09:50
Сообщение #7


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Цитата(defunct @ Jul 2 2009, 05:42) *
Всегда думал что над (unsigned int) может производиться только строго логический сдвиг. Арифметический же должен выполняться исключительно над (signed) переменными.
Да, вы правы. Я неправильно указал тип сдвига. Конечно же логический сдвиг, без учета знака.
Go to the top of the page
 
+Quote Post
777777
сообщение Jul 2 2009, 10:30
Сообщение #8


Профессионал
*****

Группа: Участник
Сообщений: 1 091
Регистрация: 25-07-07
Из: Саратов
Пользователь №: 29 357



Цитата(defunct @ Jul 2 2009, 03:42) *
>> - обозначает сдвиг вправо.

x >> n
сдвиг переменной x вправо на n разрядов.

пример:
1100 >> 1 = 0110

Правильнее (чтобы не вводить людей в заблуждение) написать так:
00001100 >> 1 = 00000110


Потому что если число знаковое, то сдвиг распространяет знак:
1100 >> 1 = 1110

Правда, если говорить строго, то это implementation defined, но в большинстве нормальных компиляторов сделано именно так.

Цитата(DpInRock @ Jul 2 2009, 06:16) *
>> в Сях - это деление на степень двойки. Вот так проще всего описать.

Ни в коем случае. Это грубая, хотя и очень распространеная ошибка.

-3 / 2 = -1
-3 >> 1 = -2

Так понятно?

Сообщение отредактировал 777777 - Jul 2 2009, 10:32
Go to the top of the page
 
+Quote Post
DpInRock
сообщение Jul 2 2009, 11:02
Сообщение #9


Гуру
******

Группа: Участник
Сообщений: 2 254
Регистрация: 4-05-07
Из: Moscow
Пользователь №: 27 515



Цитата
Вот так проще всего описать.

Ключевое слово.

А начни вы объяснять с этого примера, то кранты бы пришли человеку.
Поэтому и прозвучал совет не делать неарифметических операций над знаковыми.


--------------------
On the road again (Canned Heat)
Go to the top of the page
 
+Quote Post
defunct
сообщение Jul 2 2009, 12:12
Сообщение #10


кекс
******

Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326



Цитата(777777 @ Jul 2 2009, 13:30) *
Правильнее (чтобы не вводить людей в заблуждение) написать так:
00001100 >> 1 = 00000110

А ну да, если допустить что бывают 4-х битовые знаковые.
Однако, вы не утруждаете себя читать посты до конца.

Цитата
Правда, если говорить строго, то это implementation defined, но в большинстве нормальных компиляторов сделано именно так.

Если говорить строго, то лучше сразу обратиться непосредственно к стандарту.

[#5] The result of E1 >> E2 is E1 right-shifted E2 bit
positions. If E1 has an unsigned type or if E1 has a signed
type and a nonnegative value, the value of the result is the
integral part of the quotient of E1 divided by the quantity,
2 raised to the power E2. If E1 has a signed type and a
negative value, the resulting value is implementation-
defined.

Чтобы было ясно, что именно является implementation defined.

Cобсно определение которое предложил DpInRock, совпадает со стандартом.
а не
Цитата
Это грубая, хотя и очень распространеная ошибка.

как вы говорите.
Go to the top of the page
 
+Quote Post
777777
сообщение Jul 3 2009, 10:44
Сообщение #11


Профессионал
*****

Группа: Участник
Сообщений: 1 091
Регистрация: 25-07-07
Из: Саратов
Пользователь №: 29 357



Цитата(defunct @ Jul 2 2009, 16:12) *
Cобсно определение которое предложил DpInRock, совпадает со стандартом.

Правда он не уточнил, что это справедливо только для беззнаковых. Ну да, он же написал что использует только их.

Цитата(defunct @ Jul 2 2009, 16:12) *
а не
Цитата
Это грубая, хотя и очень распространеная ошибка.

как вы говорите.

Если следовать стандарту, то получается, что отрицательные вообще нельзя сдвигать, так как результат непредсказуем. Тем не менее все компиляторы, имеющиеся у меня под рукой, выдали результат:

-3 / 2 = -1
-3 >> 1 = -2

Так что сдвиг - это вовсе не то же самое, что и целочисленное деление.
Go to the top of the page
 
+Quote Post
defunct
сообщение Jul 3 2009, 14:29
Сообщение #12


кекс
******

Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326



Цитата(777777 @ Jul 3 2009, 13:44) *
Так что сдвиг - это вовсе не то же самое, что и целочисленное деление.

Разница то с целочисленным делением в округлении только, которое при >> (как для положительных так и для отрицательных) делается всегда к меньшему.
Go to the top of the page
 
+Quote Post
777777
сообщение Jul 3 2009, 17:21
Сообщение #13


Профессионал
*****

Группа: Участник
Сообщений: 1 091
Регистрация: 25-07-07
Из: Саратов
Пользователь №: 29 357



Цитата(defunct @ Jul 3 2009, 18:29) *
Разница то с целочисленным делением в округлении только,

При целочисленном делении не выполняется округления. Это строгая математическая операция, которая дает в результате частное и остаток.

Цитата(defunct @ Jul 3 2009, 18:29) *
которое при >> (как для положительных так и для отрицательных) делается всегда к меньшему.

При сдвиге тем более нет смысла говорить об округлении. Это - лишь сдвиг битов. И использовать его нужно только если требуются какие-то манипуляции с битами.

Впрочем, важно понимать, что деление и сдвиг не одно и то же и не использовать сдвиг для деления - оптимизирующий компилятор сам заменит его на сдвиг если это можно. А если нельзя - то не заменит!
Go to the top of the page
 
+Quote Post
Dreamer
сообщение Jul 24 2009, 07:38
Сообщение #14


Участник
*

Группа: Участник
Сообщений: 51
Регистрация: 13-01-06
Из: Санкт-Петербург
Пользователь №: 13 154



Цитата
Если следовать стандарту, то получается, что отрицательные вообще нельзя сдвигать, так как результат непредсказуем. Тем не менее все компиляторы, имеющиеся у меня под рукой, выдали результат:

Результат предсказуем как грабли и прописан в стандарте wink.gif

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

Отсюда следствие - положительные числа сдвигаются "как есть", а отрицательные числа, поскольку имеют в старшем бите единицу, сдвигаются вправо с заполнением единицей.
Пример:
0х40 >> 2 == 0x10;
0xC0 >> 2 == 0xF0;

0хС0 в десятичном представлении для знакового типа - это -64, а 0xF0 - это -16.


--------------------
Все врут (с) /M.D.House/
Go to the top of the page
 
+Quote Post
Xenia
сообщение Jul 24 2009, 07:53
Сообщение #15


Гуру
******

Группа: Модератор FTP
Сообщений: 4 479
Регистрация: 20-02-08
Из: Москва
Пользователь №: 35 237



Цитата(Dreamer @ Jul 24 2009, 10:38) *
Отсюда следствие - положительные числа сдвигаются "как есть", а отрицательные числа, поскольку имеют в старшем бите единицу, сдвигаются вправо с заполнением единицей.
Пример:
0х40 >> 2 == 0x10;
0xC0 >> 2 == 0xF0;

С чего бы вдруг 0xC0 быть байтом? Запись 0xC0 означает лишь шестандцатеричную форму записи, но никак не ограничение одним байтом. Думаете, что 0x00C0 другое число? - Нет, то же самое!
Константы такого рода считаются, как int-значения, а не char. А int это обычно 2 байта, а не один. Причем даже для 8-битных микропроцессоров (AVR). Поэтому старший бит у этого числа нулевой. А потому
0xC0 >> 2 == 0x30;
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jul 24 2009, 08:08
Сообщение #16


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(Xenia @ Jul 24 2009, 10:53) *
Думаете, что 0x00C0 другое число? - Нет, то же самое!
Если речь шла о знаковой переменной размером 1 байт, то 0x00C0 - действительно другое число. Да, при выполнении арифметических операций стандарт требует приведения меньших типов к размерности (unsigned)int. Но правило приведения знаковых типов как раз требует расширения знакового бита на добавляемые старшие разряды. Так что "тем же" будет число 0xFFC0.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
Dreamer
сообщение Jul 24 2009, 08:14
Сообщение #17


Участник
*

Группа: Участник
Сообщений: 51
Регистрация: 13-01-06
Из: Санкт-Петербург
Пользователь №: 13 154



Цитата
С чего бы вдруг 0xC0 быть байтом?


С того, что его можно объявить как signed char. Мой пример именно для signed char.

Цитата
Константы такого рода считаются, как int-значения, а не char. А int это обычно 2 байта, а не один.

Не-а. Обычно длина типа int соответствует разрядности процессора, для которого сделан компилятор.
Для 32разрядных int будет 4 байта, для 16разрядных - 2 байта.

Константы, явно заданные в выражении, действительно являются типом int.
Я оговорился и не написал, что пример придназначен для типа signed char.

Цитата
А потому 0xC0 >> 2 == 0x30

Хорошо. Тогда пример специально для Вас: wink.gif

0хС000 >> 2 == 0xF000 (Конкретно для знакового 2байтового типа).




Вот вам еще пример кода:
Код
    char c = 0xC0;
    int i = c;
    i>>=2;

char и int в настройках компилятора стоят как знаковые.
Как вы думаете, чему будет равно i после выполнения кода? Думаете, 0x0030?
Не-а. Результат будет равен 0хFFF0.
wink.gif


--------------------
Все врут (с) /M.D.House/
Go to the top of the page
 
+Quote Post
Xenia
сообщение Jul 24 2009, 08:28
Сообщение #18


Гуру
******

Группа: Модератор FTP
Сообщений: 4 479
Регистрация: 20-02-08
Из: Москва
Пользователь №: 35 237



Если это char, да еще и знаковый, то возражений у меня нет. Я же имела в виду, что выражение
if (0xC0 >> 2 == 0xF0)
было бы расценено IAR-компилятором как ложное, а
if (0xC0 >> 2 == 0x30)
как истинное.

P.S. IAR-компилятор для AVR8 понимает int, как двухбайтное знаковое целое, несмотря на то, что регистры имеют разрядность один байт.
Go to the top of the page
 
+Quote Post
Dreamer
сообщение Jul 24 2009, 08:39
Сообщение #19


Участник
*

Группа: Участник
Сообщений: 51
Регистрация: 13-01-06
Из: Санкт-Петербург
Пользователь №: 13 154



Цитата
Если это char, да еще и знаковый, то возражений у меня нет. Я же имела в виду, что выражение
if (0xC0 >> 2 == 0xF0)
было бы расценено IAR-компилятором как ложное


Ну у меня возражений тоже нет wink.gif
Я написал-то пример не к словам о приведению типов, а к высказанному в этой ветке мнению, что сдвиг вправо у отрицательных чисел непредсказуем. А правило тем-не менее есть и оно стандартное.

Цитата
P.S. IAR-компилятор для AVR8 понимает int, как двухбайтное знаковое целое, несмотря на то, что регистры имеют разрядность один байт.

Да, для Keil51 у int тоже два байта, хотя процессор там восьмиразрядный.
Это не вяжется с тем правилом, котрое я процетировал, но я его видел в литературе очень много раз.


--------------------
Все врут (с) /M.D.House/
Go to the top of the page
 
+Quote Post

2 страниц V   1 2 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 19th July 2025 - 11:58
Рейтинг@Mail.ru


Страница сгенерированна за 0.01517 секунд с 7
ELECTRONIX ©2004-2016