Форум программистов, компьютерный форум CyberForum.ru

реализация операции декримента - C++

Восстановить пароль Регистрация
 
CEBEP
105 / 105 / 9
Регистрация: 21.03.2010
Сообщений: 437
10.10.2013, 00:01     реализация операции декримента #1
На лабах задали написать алгоритм "обращенного двоичного счета", который, на сколько я понял (не удалось уточнить гуглением), представляет из себя перебор бинарный векторов в порядке лексикографического убывания. Т. е. в с++ осуществляется операцией --. Естественно, использовать -- намного проще и быстрее. Но тогда что останется от лабы?
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
void print_v(unsigned char v) {
    for (int i(8); i--; std::cout << static_cast<bool>(v & 1 << i)) {}
    std::cout << std::endl;
}
inline unsigned char& decr(register unsigned char& v) {
    if (!v) return v = -1;//чтобы не писать лишний проверок в цикле
    register unsigned char i(1);
    while (!(v & i))  i <<= 1;//Ищем первый ненулевой элемент
    v &= ~i;//Зануляем его
    while (i >>= 1) v |= i;//проставляем в младшие разряды единицы
    return v;
}
int main() {
    unsigned char b(0);
    while (decr(b))//Эквивалентно выражению while (--b)
        print_v(b);//Вывести бинарный вектор
    return 0;
}
Короче, написан вариант функции со следующими требованиями к коду:
1. Это всё-таки должен быть с++ а не какой-нибудь там ассемблер
2. Написать максимально производительный код.
Опубликовано здесь по двум причинам
1. Я доволен результатом и хочу продемонстрировать его окружающим
2. Я уверен, что найдутся люди, которые дадут дельные советы по совершенствованию написанного.
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
monolit
180 / 180 / 21
Регистрация: 24.03.2011
Сообщений: 647
Завершенные тесты: 1
10.10.2013, 00:17     реализация операции декримента #2
А чем, собственно, обусловлена такая конструкция?)
C++
1
for (int i(8); i--; std::cout << static_cast<bool>(v & 1 << i)) {}
Особой красоты коду она не придает, даже наоборот. Ну и, по моему, стоит постфиксный декримент здесь заменить на префиксный (на int, конечно, выигрыша в скорости не заметишь=), но все таки). Но это так, сугубо мое мнение.)
Jupiter
Каратель
Эксперт C++
6545 / 3965 / 226
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
10.10.2013, 00:20     реализация операции декримента #3
Цитата Сообщение от CEBEP Посмотреть сообщение
register
этот register в коде на с++ до одного места, хочешь чтоб было на регистрах - используй ассемблер
CEBEP
105 / 105 / 9
Регистрация: 21.03.2010
Сообщений: 437
10.10.2013, 00:24  [ТС]     реализация операции декримента #4
Цитата Сообщение от monolit Посмотреть сообщение
Особой красоты коду она не придает, даже наоборот.
Бесспорно. Да и вообще эта функция написана на скорую руку и без особого интереса... а с префиксным декрементом результат работы функции будет другой. Но вернёмся к --, на мой взгляд, вывод вектора тут совершенно не интересен.

Добавлено через 3 минуты
Цитата Сообщение от Jupiter Посмотреть сообщение
хочешь чтоб было на регистрах - используй ассемблер
Ну асемблеровский код использовать у меня возможности нет по причине очень поверхностного его знания. А стандарт описывает это словечко как вполне подходящее для такого случая так что почему бы и нет?

Меня больше интересует мнение профессионалав по таким вопросам как проверка например while (!(v & i)) этого условия... что тут в действительности происходит? можно ли использовать что-то более производительное чем неявное приведение типа (v & i) не равны константе 0 всегда, так что приведение типа тут по всей видимости есть.
Jupiter
Каратель
Эксперт C++
6545 / 3965 / 226
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
10.10.2013, 00:41     реализация операции декримента #5
Цитата Сообщение от CEBEP Посмотреть сообщение
А стандарт
A register specifier is a hint to the implementation that the variable so declared will be heavily used.
[ Note: the hint can be ignored and in most implementations it will be ignored if the address of the variable
is taken. This use is deprecated (see D.4). — end note
...
CEBEP
105 / 105 / 9
Регистрация: 21.03.2010
Сообщений: 437
10.10.2013, 01:33  [ТС]     реализация операции декримента #6
спасибо, уберу.

Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
    unsigned char b(0);
00A81277  xor         bl,bl  
00A81279  lea         esp,[esp]  
    while (decr(b))//Эквивалентно выражению while (--b)
00A81280  test        bl,bl  
00A81282  jne         main+19h (0A81289h)  
00A81284  or          bl,0FFh  
00A81287  jmp         main+3Ah (0A812AAh)  
00A81289  mov         al,1  
00A8128B  test        al,bl  
00A8128D  jne         main+26h (0A81296h)  
00A8128F  nop  
00A81290  add         al,al  
00A81292  test        bl,al  
00A81294  je          main+20h (0A81290h)  
00A81296  mov         cl,al  
00A81298  not         cl  
00A8129A  and         bl,cl  
00A8129C  shr         al,1  
00A8129E  je          main+36h (0A812A6h)  
00A812A0  or          bl,al  
00A812A2  shr         al,1  
    while (decr(b))//Эквивалентно выражению while (--b)
00A812A4  jne         main+30h (0A812A0h)  
00A812A6  test        bl,bl  
00A812A8  je          main+81h (0A812F1h)  
00A812AA  movzx       eax,bl  
        print_v(b);//Вывести бинарный вектор
00A812AD  mov         edi,8  
00A812B2  mov         esi,100h  
00A812B7  mov         dword ptr [ebp-4],eax  
00A812BA  lea         ebx,[ebx]  
00A812C0  ror         esi,1  
00A812C2  mov         ecx,dword ptr ds:[0A8303Ch]  
00A812C8  test        esi,eax  
00A812CA  setne       al  
00A812CD  movzx       eax,al  
00A812D0  push        eax  
00A812D1  call        dword ptr ds:[0A8302Ch]  
00A812D7  mov         eax,dword ptr [ebp-4]  
00A812DA  dec         edi  
00A812DB  jne         main+50h (0A812C0h)  
00A812DD  push        dword ptr ds:[0A83024h]  
00A812E3  mov         ecx,dword ptr ds:[0A8303Ch]  
00A812E9  call        dword ptr ds:[0A83028h]  
00A812EF  jmp         main+10h (0A81280h)  
00A812F1  pop         edi  
00A812F2  pop         esi  
    return 0;
Вот что вывалилось при компиляции /O2. Видимо, он действительно вставился как инлайн. Но это единственный вывод, который я могу уверенно сделать по данному коду. Не могли бы вы её прокомментировать?

Добавлено через 8 минут
К стаи, на сколько я понял, переменные действительно возникают только в регистрах!

Добавлено через 4 минуты
*его - код а не вывод))

Добавлено через 5 минут
что-то меня поплавило к часу ночи. Короче, разобраться помогите)))

Добавлено через 24 минуты
Assembler
1
2
3
4
    while (--b)
010512BC  mov         al,byte ptr [ebp-1]  
010512BF  dec         al  
010512C1  dec         ebx
А как бы всё могло быть просто...
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
12.10.2013, 18:53     реализация операции декримента
Еще ссылки по теме:

C++ Элементарные операции
C++ Побитовые операции
Битовые операции C++
Перегрузка операции ~ C++
C++ Побитовые операции

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
CEBEP
105 / 105 / 9
Регистрация: 21.03.2010
Сообщений: 437
12.10.2013, 18:53  [ТС]     реализация операции декримента #7
короче печаль. ковырялся с этой ерундой полдня, даже 50 рублей отдал чтобы отчет на цветном принтере распечатать. Преподу вообще плевать - посмотрел, зачел... отчет не открывал даже...
Yandex
Объявления
12.10.2013, 18:53     реализация операции декримента
Ответ Создать тему
Опции темы

Текущее время: 05:18. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru