在整数c ++中访问的第二个字节背后的逻辑是什么?

时间:2015-04-17 16:30:10

标签: c++

我的问题是如果我尝试访问整数变量的第二个内存位置会发生什么?

在c ++中,整数需要存储2个字节..

int b = 10;

[10] = 7936(地址65524) [10] = 768(地址65514)

这里两个地址都对应于整数值b = 10的第二个字节..为什么它在两个不同的地址给出2个不同的值,我的数值背后的数学逻辑是什么?

描述: 现在这将存储在一些内存位置..在我的程序中,它存储在以下的地址中 65523和65524

现在如果我用指针编写"值在内存位置65523" ..我会给我原始值10 .. 但是如果我用指针写出"值在内存位置65514" ..它会给我一个特定的数字..(这里给出7936。

在同一程序中与另一个对象,如果我再次在某个内存位置存储我的int b = 10,如65513和65514 ......

这次如果我访问65513位置,它会给我10 .. 但如果我尝试访问65514位置,它在我的情况下给出了具体值768 ..

所以我的问题是这个特定值背后的逻辑是什么? 因为所有这些值在所有机器中都是相同的(小端)..

我想知道对于相同的整数变量,如何在两个不同的地址上给我两个不同的值。

我想要对我的数字进行数学表示,以便我能够轻松理解它。

这是用于访问整数变量b的第二个字节的以下代码。

#include<iostream.h>
#include<conio.h>

class t1
{
    int x;
    int y,z;
    public:
    char a;
    int b;
    void view();
};

void t1::view()
{
    x=1;
    y=2;
    z=3;
    a='x';
    b=10;
    int *a1;
    //addresses of all variables
    cout<<(unsigned int)&x<<" "<<(unsigned int)&y<<" "<<(unsigned int)&z<<" "<<(unsigned int)&a<<" "<<(unsigned int)&b<<"\n";
    a1=&x;
    //loop for accessing 2nd byte of "b"
    for(int i=0;i<5;i++)
    {
        if(i==3)
        {
            cout<<"a+"<<i<<" "<<(char)*(a1+i)<<" "<<(unsigned int)(a1+i)<<"\n";
            continue;
        }
        cout<<"a+"<<i<<":"<<*(a1+i)<<" "<<(unsigned int)(a1+i)<<"\n";
    }
} 

void main()
{
    t1 x,y;
    clrscr();
    cout<<"a="<<(unsigned int)&x.a<<" "<<"b="<<(unsigned int)&x.b<<" ";
    x.view();
    y.view();
    getch();
}

2 个答案:

答案 0 :(得分:1)

  • 我们的十进制编号系统有10位数字(0到9)。然而,我们可以通过使用定义顺序的多个数字来表示更大的数字。所以你有数字0,1,2,3,4,5,6,7,8和9.当你没有数字时你会怎么做?你引入另一个数字并重新开始:10,11,12等。有2个十进制数字,你可以代表10 ^ 2 = 100个数字。使用3位十进制数字,您可以表示10 ^ 3 = 1000个数字。你可以看到模式:DigitRange ^ DigitCount。
  • 一个位可以有两种状态之一:0和1.一位基本上是一个二进制数字。
  • 字节是8位的数据类型。如果位是数字,则字节是8位数字(包括前面的0)。因此,它可以具有2 ^ 8 = 256个状态中的一个。因此,它可以表示256个数字(0到255)。
  • 现在,如果您有一个占用2个字节的整数数据类型,那么您可以存储256 ^ 2个状态。如果字节是数字,则此新类型是2位数字。和以前一样,每个数字都可以是0到255之间的任何值。当你需要代表一个更大的数字时,你将下一个最高有效数字增加1并重新开始。

现在,作为最后一点的示例,考虑一个占用2个字节的整数,以及如何解释它。右字节的重要性为1,左字节的重要性为256:

  • [0 0] == 0
  • [0 1] == 1
  • [0 10] == 10
  • [0 255] == 255
  • [1 0] == 256
  • [1 1] == 257
  • [1 255] = 511
  • [2 0] == 512
  • [2 1] = 513
  • [30 255] == 7935
  • [31 0] == 7936
  • [31 1] == 7937

......等等。

要验证结果,请尝试以下代码:

auto value = 512;
auto ptr = (char*)&value;

for (auto i = 0; i < sizeof(value); i++)
{
    auto bytePtr = ptr + i;     
    int byteValue = *bytePtr;
    std::cout << (void*)bytePtr << ": " << byteValue << std::endl;
}

最低内存地址是否包含最高或最低有效字节的问题称为endianness

在大端计算机中,最重要的字节(在我们的示例中,值为256的字节)存储在最低地址和最低有效字节(值为1的字节中) )存储在最高地址。在小端计算机中,情况恰恰相反。

从上面和你的描述中,我们可以推断出你是一个小端架构。

答案 1 :(得分:1)

  

“那么背后的逻辑是什么?”

整数值由CPU使用固定数量的字节(int通常为4)表示,并按特定顺序表示如何处理这些字节。

单个字节可以保存0 - 255的值。所以是的,使用更大范围内的值会影响另一个字节。

如果您正在寻找像

这样的工会
union intLayout {
    int ival;
    unsigned char bytes[4];
};

您可以实际检查机器上的整数存储器布局。

int main() {
    intLayout layout;
    layout.ival=10;

    std::cout << std::hex 
              << "0x" << (unsigned)layout.bytes[0] << ", "
              << "0x" << (unsigned)layout.bytes[1] << ", "
              << "0x" << (unsigned)layout.bytes[2] << ", "
              << "0x" << (unsigned)layout.bytes[3] << std::endl;

    return 0;
}

Ideone Sample的输出:

0xa, 0x0, 0x0, 0x0

了解此布局的关键是了解主机CPU架构使用的endianess

上面的示例表明我们有一个 little endian 架构,它使用第一个字节作为LSB(最低有效字节)。

对于大端架构,输出看起来像:

0x0, 0x0, 0x0, 0xa

更多例子

layout.ival=538;

Little endian:

0x1a, 0x2, 0x0, 0x0

Big endian:

0x0, 0x0, 0x2, 0x1a 

layout.ival=215;

Little endian:

0xd7, 0x0, 0x0, 0x0

Big endian:

0x0, 0x0, 0x0, 0xd7