2015-03-12 1 views
1

У меня есть этот пример кода:C++ сдвига вправо, проблемы XOR

#include "stdafx.h" 
#include "stdio.h" 
#include "stdlib.h" 
#include "math.h" 
#ifndef uint32 
#define uint32 unsigned long int 
#endif 
#define L(a) printf("\n%x >> 1 = %x", a, a>>1) 
int _tmain(int argc, _TCHAR* argv[]) 
{ 
    uint32 a = 2941362065; 
    uint32 b = 509727776; 
    uint32 c = a^b; 
    L(a^b); 
    printf("\n%x >> 1 = %x", c , c>>1); 
    return 0; 
} 

Моя проблема заключается в том, что L (а) возвращает

b1304bb1 >> 1 = a0617581 

в то время как

printf("\n%x >> 1 = %x", c , c>>1); 

возвращается

b1304bb1 >> 1 = 589825d8 

Последнее значение - это то, которое кажется правильным, поскольку калькулятор окон возвращает его. Этот код работает на WinXP 32. Есть идеи?

+1

Ну, это то, что вы получаете за использование макросов, вы этого заслуживаете. Дело в том, что 'L (a^b)' становится 'a^b >> 1', который затем оценивается как' a^(b >> 1) '. –

ответ

1

Вы получаете укушенным способом макросов в работе C. Правильный сдвиг имеет более высокий приоритет, чем xor, так что это произойдет первым. Вы должны окружать все экземпляры a в определении L с круглыми скобками.

2
L(a^b) becomes printf("\n%x >> 1 = %x", a^b, a^b>>1) 

Старшинство >> 5 в то время как^9 (см this), что означает, что вызов выше, дает те же результаты, что и следующий (примечание дополнительных круглых скобках):

printf("\n%x >> 1 = %x", a^b, a^(b>>1)) 

Вы должны изменить ваше определение L, добавив круглые скобки вокруг аргументов:

#define L(a) printf("\n%x >> 1 = %x", (a), (a)>>1) 

Лучше использовать функцию вместо макроса L.

+0

Большое спасибо. Это решило мою мистерию. Я не мог спать пару ночей, потому что это было так. –

1

Макрос расширяется, чтобы:

printf("\n%x >> 1 = %x", a^b, a^b >> 1) 

Поскольку << имеет более высокий приоритет, чем ^ (см here), он был в стадии обработки, как a^(b >> 1), а не (a^b) >> 1.

Вы должны круглые скобки в макрос:

#define L(a) printf("\n%x >> 1 = %x", (a), (a)>>1) 

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

Но еще лучше, чтобы не использовать макрос, когда функция будет работать так же хорошо.