我想在我的程序中使用以下代码,但是gcc不允许我将我的1转移到31以上。
sizeof(long int)
显示8,所以这并不意味着我可以离开直到63?
#include <iostream>
using namespace std;
int main(){
long int x;
x=(~0 & ~(1<<63));
cout<<x<<endl;
return 0;
}
编译输出以下警告:
left shift `count >= width` of type [enabled by default] `x=(~0 & ~(1<<63))`;
^
,输出为-1。如果我离开了31位,我得到2147483647正如预期的那样。
我希望打开除 MSB 之外的所有位,从而显示数据类型可以容纳的最大值。
答案 0 :(得分:7)
虽然x
类型为long int
,但1
不是1
。 int
是1<<63
,因此(static_cast<long int>(1) << 63)
确实未定义。
按照Wojtek的建议尝试1L << 63
或{{1}}。
答案 1 :(得分:3)
您不能使用1(默认情况下为int)将其移出int边界。
除了MSB开启之外,还有一个更简单的方法来获取所有位&#34;对于特定的数据类型
#include <iostream>
#include <limits>
using namespace std;
int main(){
unsigned long int max = std::numeric_limits<unsigned long int>::max();
unsigned long int max_without_MSB = max >> 1;
cout<< max_without_MSB <<endl;
return 0;
}
注意无符号类型。没有numeric_limits
:
#include <iostream>
using namespace std;
int main() {
long int max = -1;
unsigned long int max_without_MSB = ((unsigned long int)max) >> 1;
cout << max_without_MSB << endl;
return 0;
}
答案 2 :(得分:2)
首先让我说一下有关转变的一些事情,这是你问题的根源:
无法保证long int
实际上是64位宽。
我能想到的最通用的方法是使用std::numeric_limits
:
static_cast<long int>(1) << (std::numeric_limits<long int>::digits - 1);
现在你甚至可以制作一个constexpr模板函数:
template <typename Integer>
constexpr Integer foo()
{
return static_cast<Integer>(1) << (std::numeric_limits<Integer>::digits - 1);
}
因此,使用static_cast<long int>(1) << (std::numeric_limits<long int>::digits - 1)
替换班次将解决您的问题,但有更好的方法:
std::numeric_limits
包含许多有用的内容,包括:
std::numeric_limits<T>::max(); // the maximum value T can hold
std::numeric_limits<T>::min(); // the minimum value T can hold
std::numeric_limits<T>::digits; // the number of binary digits
std::numeric_limits<T>::is_signed(); // well, do I have to explain? ;-)
有关完整列表,请参阅cppreference.com。您应该更喜欢标准库提供的工具,因为它很可能会有更少的错误,其他开发人员会立即知道它。
答案 3 :(得分:2)
你的头衔有误导性;如果long
确实那么大,31
可以超越long
位。但是,您的代码会移动1
,即int
。
在C ++中,表达式的类型由表达式本身决定。表达式XXXXX
具有相同的类型,无论如何;如果您稍后转到double foo = XXXXX;
,则并不意味着XXXXX
是双倍的 - 这意味着从XXXXX
到double
的任何转化都会发生。
如果你想左移一长,那么明确地做,例如1L << 32
或((long)1) << 32
。请注意,long
的大小因平台而异,因此如果您不希望代码在其他系统上运行时中断,则必须采取进一步措施,例如使用固定宽度类型,或者转移CHAR_BIT * sizeof(long) - 1
。
您的预期代码还有另一个问题:如果1L << 63
为64位或更低,long
会导致未定义的行为。这是因为有符号整数溢出;左移定义与重复乘以2相同,因此尝试“移入符号位”会导致溢出。
要解决此问题,请使用无符号类型,以便可以切换到MSB,例如1ul << 63
。
从技术上讲,还存在另一个问题:~0
如果你没有使用2的补充系统,那就不能做你想做的事情,但是现在忽略这种情况是非常安全的。
使用long x = ~0 & ~(1 << 63)
查看您的总体意图。写这个的更简单的方法是:
long x = LONG_MAX;
由<climits>
定义。如果你想在所有平台上使用64位,那么
int64_t x = INT64_MAX;
NB。如果您不打算使用负值,请分别使用unsigned long x
和uint64_t
。
答案 4 :(得分:1)
除非明确提及,否则C中数值的默认数据类型为整数。
在这里你必须输入1作为 long int ,否则它将是一个int。