C中的指针与类型转换

时间:2017-04-27 17:56:13

标签: c arrays pointers casting

#include<stdio.h> 
int main() 
{ 
    int a; 
    char *x; 
    x = (char *) &a; 
    a = 512; 
    x[0] = 1; 
    x[1] = 2; 
    printf("%d\n",a); 
    return 0; 
}

我无法理解输出如何是513甚至是机器依赖的事实?我可以感觉到类型转换正在发挥重要作用,但幕后发生了什么,有人可以帮助我想象这个问题吗?

5 个答案:

答案 0 :(得分:2)

int a以4个字节存储在内存中。数字512在您的计算机上显示为:

0 2 0 0

当您分配到x[0]x[1]时,会将其更改为:

1 2 0 0

这是数字513

这与机器有关,因为C语言没有指定多字节数字的字节顺序。

答案 1 :(得分:2)

为简化起见假设如下:

  • int的大小是4(以字节为单位)
  • 任何指针类型的大小为8
  • char的大小是1个字节

在第3行x中引用a作为char,这意味着x认为他指向了一个char(他不知道a实际上是一个int。

第4行是为了让你感到困惑。不。

第5行 - 因为x认为他指向一个字符x [0] = 1只改变a的第一个字节(因为他认为他是一个字符)

第6行 - 再一次,x只改变了第二个字节。

请注意,第5行和第6行中的值覆盖了第4行中的值。 a的值现在为0 ... 0000 0010 0000 0001(513)。

现在当我们打印一个int作为int时,所有4个字节都将被视为预期。

答案 2 :(得分:1)

  

我无法理解输出如何是513甚至机器依赖的事实

输出是实现定义的。它取决于CPU对整数的解释中的字节顺序,通常称为endianness

  

我可以感觉到类型转换正在发挥重要作用

代码将a的值重新解释为int,作为字节数组。它使用两个初始字节,保证可以工作,因为int的大小至少为两个字节。

  

有人可以帮我看看这个问题吗?

int由多个字节组成。它们可以作为一个表示整数的单元来寻址,但它们也可以作为字节集合进行寻址。 int的值取决于您设置的字节数,以及CPU对整数解释中这些字节的顺序。

看起来您的系统将最低有效字节存储在最低地址,因此将12存储在偏移为零的结果,并生成此布局:

Byte 0 Byte 1 Byte 2 Byte 3
------ ------ ------ ------
     1      2      0      0

整数值可以按如下方式计算:

1 + 2*256 + 0*65536 + 0*16777216

答案 3 :(得分:1)

通过x char *,并将其指向a的地址int,您可以使用x修改代表a的单个字节。

您看到的输出表明int以小端格式存储,这意味着最低有效字节首先出现。但是,如果您在另一个系统上运行此代码(例如,大型enidan的Sun SPARC计算机),则可能会发生这种情况。

您首先将a设置为512.在十六进制中,即0x200。因此a的内存假定为小端格式的32位int,其布局如下:

-----------------------------
| 0x00 | 0x02 | 0x00 | 0x00 |
-----------------------------

接下来,将x[0]设置为1,这将更新a表示中的第一个字节(在这种情况下保持不变):

-----------------------------
| 0x01 | 0x02 | 0x00 | 0x00 |
-----------------------------

然后将x[1]设置为2,这会更新a表示中的第二个字节:

-----------------------------
| 0x01 | 0x02 | 0x00 | 0x00 |
-----------------------------

现在a的值为0x201,十进制为513。

答案 4 :(得分:1)

除了之前的答案之外,让我试着为你解决这个问题:

#include<stdio.h> 
int main() 
{ 
    int a;            //declares an integer called a
    char *x;          //declares a pointer to a character called x
    x = (char *) &a;  //points x to the first byte of a
    a = 512;          //writes 512 to the int variable
    x[0] = 1;         //writes 1 to the first byte
    x[1] = 2;         //writes 2 to the second byte
    printf("%d\n",a); //prints the integer
    return 0; 
}

请注意,我写了第一个字节和第二个字节。根据平台的字节顺序和整数的大小,您可能得不到相同的结果。

让我们看一下 32位 4 Bytes 大小整数的内存:

Little endian systems

first byte | second byte | third byte | forth byte
0x00           0x02        0x00         0x00

现在将1分配给第一个字节,将2分配给第二个字节,使我们留下:

first byte | second byte | third byte | forth byte
0x01           0x02        0x00         0x00

请注意,第一个字节更改为0x01,而第二个字节已经0x02。 内存中的这个新数字相当于 little endian 系统上的513

大端系统

让我们看一下如果您在 big endian 平台上尝试此操作会发生什么:

first byte | second byte | third byte | forth byte
0x00           0x00        0x02         0x00

这次将1分配给第一个字节,将2分配给第二个字节给我们留下了:

first byte | second byte | third byte | forth byte
0x01           0x02        0x02         0x00

相当于16,908,800的整数。