为什么对于 long int 数据类型,左位移位<<移位不会超过 31?
Why doesn't left bit shift << shift beyond 31 for long int datatype?
我想在我的程序中使用以下代码,但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之外的所有位都被打开,从而显示数据类型可以容纳的最大值。
虽然您的x
是long int
类型,但1
不是。1
是int
,所以1<<63
确实没有定义。
试试(static_cast<long int>(1) << 63)
,或者Wojtek建议的1L << 63
不能使用1(默认为int)将其移出int边界。
对于特定的数据类型,有一种更简单的方法可以使"除MSB之外的所有位都打开"
#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;
}
注意unsigned类型。无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;
}
你的标题是误导;如果long
确实有那么大,那么long
可以超越31
位。但是你的代码改变了1
,这是一个int
。
在c++中,表达式的类型由表达式本身决定。表达式XXXXX
无论如何都具有相同的类型;如果你后来转到double foo = XXXXX;
,这并不意味着XXXXX
是双精度,它意味着从XXXXX
转换到double
。
如果你想左移一个长字符,那么显式地进行,例如1L << 32
或((long)1) << 32
。请注意,long
的大小在不同的平台上是不同的,所以如果你不想让你的代码在不同的系统上运行时中断,那么你必须采取进一步的措施,比如使用固定宽度的类型,或者通过CHAR_BIT * sizeof(long) - 1
来移动。
您的预期代码还有另一个问题:如果long
是64位或更少,1L << 63
会导致未定义的行为。这是因为有符号整数溢出;左移的定义与2的重复乘法相同,因此尝试"移到符号位"会导致溢出。
要解决这个问题,使用unsigned类型,它可以很好地转移到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
。
首先让我说明一些关于你的问题根源的变化:
不能保证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)
替换shift会解决你的问题,但是有一个更好的方法:
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获取完整列表。您应该更喜欢标准库提供的功能,因为它很可能会有更少的错误,并且其他开发人员立即知道它。
除非明确说明,否则C中数值的默认数据类型是整型。
这里必须将1强制转换为long int,否则它将是int型。
- 为什么在全局范围内使用"extern int a"似乎不行?
- int(c) 和 c-'0' 之间的区别。C++
- 从"int*"强制转换为"unsigned int"会丢失精度错误
- 为什么野牛仍在使用"int yylex(void)",却找不到"int yylex(YYS
- 有符号的int和int-有没有一种方法可以在C++中区分它们
- 请解释这句话(cout<<1+int((a<b)^((b-a)&1) )<<endl
- 是否可以从int转换为enum类类型
- 不能在初始值设定项列表中将非常量表达式从类型 'int' 缩小到'unsigned long long'
- 向量 <int> a {N, 0} 和 int arr a[N] = {0} 的时间复杂度有什么区别
- 呼叫运营商<<临时
- 'short int'持有的值溢出,但"自动"不会溢出?
- 如何在C++中将一个无符号的 int 转换为两个无符号的短裤?
- 调用'begin(int [n])'没有匹配函数
- 错误:调用"std::vector<:vector<int>>::p ush_back(std::vector<std::__cxx11::basic_string<
- 为什么将此对向量&lt; map&lt; int,int&gt;&gt;中的地图进行更新.失败
- 如何加入向量&lt; int&gt;到C 中的单个INT
- 是numeric_limits&lt; int&gt; :: is_modulo从逻辑上矛盾
- 运营商&lt;&lt;无法访问班级的私人int
- std::pair的默认构造函数<>将基本类型(int等)设置为零
- 如何显示/打印字符串对象?cout & lt; & lt;Int工作,count <<字符串