c++ - 内存代表多长时间?

标签 c++ c++11 bitwise-operators

我不是高级C ++程序员。但是我已经使用C ++很久了。所以,我喜欢玩它。最近,我在考虑以编程方式最大化变量的方法。所以我尝试按位运算符用1填充变量。然后是signedunsigned问题。我对内存表示的知识不是很好。但是,我最终写了下面的代码,它们对signedunsigned shortintlong都适用(尽管intlong基本相同)。不幸的是,对于long long,程序失败。

那么,long long的幕后发生了什么?它在内存中如何表示?此外,在C ++中是否有更好的方法可以实现相同的目的?

#include <bits/stdc++.h>
using namespace std;



template<typename T>
void Maximize(T &val, bool isSigned)
{
    int length = sizeof(T) * 8;
    cout << "\nlength = " << length << "\n";

    // clearing
    for(int i=0; i<length; i++)
    {
        val &= 0 << i;
    }

    if(isSigned)
    {
        length--;
    }

    val = 1 << 0;
    for(int i=1; i<length; i++)
    {
        val |= 1 << i;

        cout << "\ni = " << i << "\nval = " << val << "\n";
    }
}


int main()
{
    long long i;

    Maximize(i, true);

    cout << "\n\nsizeof(i) = " << sizeof(i) << " bytes" << "\n";
    cout << "i = " << i << "\n";

    return 0;
}

最佳答案

您的代码的基本问题在语句中

val &= 0 << i;




val |= 1 << i;


如果val长于int

在第一个表达式中,0 << i总是(最可能)始终为0,与i无关(从技术上讲,它具有下面描述的相同的未定义行为,但是您不太可能会遇到问题。)因此不需要整个循环;所有的语句都做同样的事情,就是将val归零。当然,val = 0;是一种更简单的编写方式。

问题1 << i是常量文字1int(因为它足够小,可以表示为int,而int是用于整数常量的最窄表示形式)。由于1int,因此1 << i也是如此。如果i大于或等于int中的值位数,则该表达式具有未定义的行为,因此从理论上讲,结果可以是任何值。但是,实际上,结果的宽度很可能与int相同,因此仅会影响低位。

当然可以将1转换为T类型(尽管通常来说,对T进行签名时可能需要格外小心),但是将1转换为无符号形式会更容易使用Tcstdint中定义的最大宽度无符号整数类型,键入至少与uintmax_t一样宽的字符:

val |= std::uintmax_t(1) << i;


在实际代码中,通常会看到最宽整数类型是long long的假设:

val |= 1ULL << i;


如果程序从不尝试使用扩展的整数类型实例化模板,则该方法会很好地工作。



当然,这不是为整数类型找到最大值的方法。正确的解决方案是#include <limits>,然后使用std::numeric_limits<T>::max()的适当专业化



C ++仅允许使用一种表示正(和无符号)整数的方式,并使用三种可能的表示负号的整数。正整数和无符号整数仅表示为二进制表示形式的位序列。可能也有填充位,带符号的整数只有一个符号位(在正整数的情况下必须为0),因此即使位数数量也不能保证表示中有8*sizeof(T)个有用的位已知一个字节的字节数为8(理论上,它可以更大)。 [注1]

负号整数的符号位始终为1,但值位有三种不同的格式。最常见的是“二进制补码”,其中被解释为正数的值位数将比该数字的实际值精确多2k,其中k是值位数。 (这等效于为符号位指定2-k的权重,因此将其称为2s补码。)

另一种选择是“一个人的补码”,其中所有值位都单独反转。这与二的补码表示形式完全不同。

第三个允许的替代方法是“符号幅度”,其中值位恰好是负数的绝对值。此表示形式通常用于浮点值,但很少用于整数值。

符号幅度和补码都具有以下缺点:存在表示“负0”的位模式。另一方面,补码表示具有最大负可表示值的大小比最大正可表示值的大小大的结果,结果-xx/-1都可能溢出,从而导致不确定的行为。



笔记


我相信从理论上讲,可以在值位和符号位之间插入填充,但是我当然不知道在现实世界中具有该功能的任何实现。但是,尝试将1移到符号位的位置是未定义的行为,这一事实使得假设符号位与值位相邻是不正确的。

关于c++ - 内存代表多长时间?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46633804/

相关文章:

c++ - C++下的跨进程交互

c - 为什么 if(-8 & 7) 返回 false

javascript - 使用按位运算符(JSFeat)修改图像像素

c++ - 调用 ADL 时,表达式和 namespace 之间是否会发生冲突?

c++ - 交叉编译qt(linux/mingw -> windows): various undefined references

c++ - 将枚举值映射到 C++ 中的类型

c++ - 引用能够引用不同的对象(不在迭代/循环体中)

c++ - C/C++ : Bitwise operators on dynamically allocated memory

C++ 游戏状态系统

c++ - 在命名空间中声明变量,在 main 中定义它,使其对所有其他文件可见