移位计数 >= 类型和宏的宽度与内联函数

shift count >= width of type and macros vs inline function

本文关键字:函数 类型 gt      更新时间:2023-10-16

我正在处理一些位操作,并且在放入宏和内联函数的同一行代码中遇到奇怪的不同输出。该函数返回64位掩码,该掩码从N -位置:(~0<<N) - (~0<<(N+L))中具有L位活动位。谁能告诉我输出不一样的原因?

#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)

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

你只能合法地移动少于整数类型的位数

如此:

#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

你的编译器警告它

你的移动量(from_bit + nbits)大于你正在使用的字体的大小。

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