2013-04-10 77 views
-1

我正在处理一些操作,并且将相同行代码的奇怪的不同输出放入宏和内联函数中。该函数返回具有来自NL活动位的64位掩码,该掩码具有第(~0<<N) - (~0<<(N+L))位。有人能告诉我为什么产量不同吗?shift count> =类型和宏的宽度vs内联函数

#include <iostream> 
#include <bitset> 
using namespace std; 

#define ONES (~0UL) 

#define MASK(from_bit, nbits) \ 
    (ONES << (from_bit)) - (ONES << ((from_bit) + (nbits))) 

inline unsigned long int mask(size_t from_bit, size_t nbits) { 
    return (ONES << from_bit) - (ONES << (from_bit + nbits)); 
} 

int main(int argc, char **argv) { 
    cout << "using #define:   " << bitset<64>(MASK(63, 3)) << endl; 
    cout << "using inline function: " << bitset<64>(mask(63, 3)) << endl; 
    return 0; 
} 

输出:

$ g++ -o test main.cc 
main.cc: In function 'int main(int, char**)': 
main.cc:15: warning: left shift count >= width of type 
$ ./test 
using #define:   1000000000000000000000000000000000000000000000000000000000000000 
using inline function: 1000000000000000000000000000000000000000000000000000000000000100 
                       ------^ 

-O3选项编译:

$ g++ -O3 -o test2 main2.cc 
main.cc: In function 'int main(int, char**)': 
main.cc:15: warning: left shift count >= width of type 
$ ./test2 
using #define:   1000000000000000000000000000000000000000000000000000000000000000 
using inline function: 0000000000000000000000000000000000000000000000000000000000000000 
       ------^ 

编译器的信息:

$ g++ --version 
i686-apple-darwin11-llvm-g++-4.2 (GCC) 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2336.9.00) 
+1

可能是因为你在超过64位的移位(最多)64位类型,导致不确定的行为。注意你的编译器警告! – Yuushi 2013-04-10 10:54:02

+0

所以溢出左移并不会自动删除位,因为我认为... – pckben 2013-04-10 11:06:19

回答

0

您不应该忽略编译器警告。它告诉你有一个问题。

您可以合法地只移位少于整数类型中的位数。

这工作:

#include <iostream> 
#include <bitset> 
using namespace std; 

#define ONES (~0ULL) 

#define MASK(from_bit, nbits) \ 
    (ONES << (from_bit)) - (ONES << (from_bit) << (nbits)) 

inline unsigned long long mask(unsigned from_bit, unsigned nbits) { 
    return (ONES << from_bit) - (ONES << from_bit << nbits); 
} 

int main(int argc, char **argv) { 
    cout << "using #define:   " << bitset<64>(MASK(63, 3)) << endl; 
    cout << "using inline function: " << bitset<64>(mask(63, 3)) << endl; 
    return 0; 
} 

输出(ideone):

using #define:   1000000000000000000000000000000000000000000000000000000000000000 
using inline function: 1000000000000000000000000000000000000000000000000000000000000000 
+0

谢谢,'ONES << from_bit << nbits'部分的不错技巧。我甚至不必为面具使用ULL。 – pckben 2013-04-10 11:07:57

+0

我将'UL'改为'ULL'和'unsigned long'改为'unsigned long long',以确保类型中有64位。 'unsigned long'至少为32位,即可以小于64.'unsigned long long'保证为64位或更大。而且,移位计数很小,不需要使用任何可能大于'unsigned int'的值(例如'long'或'size_t')。 – 2013-04-10 11:10:17

0

你的编译器警告说它。

您的转移金额(from_bit + nbits)大于您所用类型的大小。

宏和函数的区别在于,前者没有类型检查。