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

 
 
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

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

 


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


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