简体   繁体   English

C中的指针与类型转换

[英]Pointers in C with typecasting

#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; 
}

I'm not able to grasp the fact that how the output is 513 or even Machine dependent ? 我无法掌握输出是如何513甚至机器依赖的事实? I can sense that typecasting is playing a major role but what is happening behind the scenes, can someone help me visualise this problem ? 我可以感觉到类型转换正在发挥重要作用,但幕后发生了什么,有人可以帮助我想象这个问题吗?

The int a is stored in memory as 4 bytes. int a作为4个字节存储在内存中。 The number 512 is represented on your machine as: 数字512在您的机器上表示为:

0 2 0 0

When you assign to x[0] and x[1] , it changes this to: 分配给x[0]x[1] ,它将其更改为:

1 2 0 0

which is the number 513 . 这是513

This is machine-dependent, because the order of bytes in a multi-byte number is not specified by the C language. 这与机器有关,因为C语言没有指定多字节数字中的字节顺序。

For simplifying assume the following: 为简化假设以下内容:

  • size of int is 4 (in bytes) int的大小是4(以字节为单位)
  • size of any pointer type is 8 任何指针类型的大小为8
  • size of char is 1 byte char的大小是1个字节

in line 3 x is referencing a as a char, this means that x thinks that he is pointing to a char (he has no idea that a was actually a int. 在第3行x中引用a作为char,这意味着x认为他指向了一个char(他不知道a实际上是一个int。

line 4 is meant to confuse you. 第4行是为了让你感到困惑。 Don't. 别。

line 5 - since x thinks he is pointing to a char x[0] = 1 changes just the first byte of a (because he thinks that he is a char) 第5行 - 因为x认为他指向一个字符x [0] = 1只改变a的第一个字节(因为他认为他是一个字符)

line 6 - once again, x changed just the second byte of a. 第6行 - 再一次,x改变了a的第二个字节。

note that the values put in lines 5 and 6 overide the value in line 4. the value of a is now 0...0000 0010 0000 0001 (513). 请注意,第5行和第6行中的值位于第4行的值之上.a的值现在为0 ... 0000 0010 0000 0001(513)。

Now when we print a as an int, all 4 bytes would be considered as expected. 现在当我们打印一个int作为int时,所有4个字节都将被视为预期。

I'm not able to grasp the fact that how the output is 513 or even Machine dependent 我无法理解输出如何是513甚至是机器依赖的事实

The output is implementation-defined. 输出是实现定义的。 It depends on the order of bytes in CPU's interpretation of integers, commonly known as endianness . 它取决于CPU对整数解释的字节顺序 ,通常称为字节序

I can sense that typecasting is playing a major role 我可以感觉到类型转换正在发挥重要作用

The code reinterprets the value of a , which is an int , as an array of bytes. 代码重新解释的值a ,这是一个int ,作为字节数组。 It uses two initial bytes, which is guaranteed to work, because an int is at least two bytes in size. 它使用两个初始字节,保证可以工作,因为int大小至少为两个字节。

Can someone help me visualise this problem? 有人可以帮助我想象这个问题吗?

An int consists of multiple bytes. int由多个字节组成。 They can be addressed as one unit that represents an integer, but they can also be addressed as a collection of bytes. 它们可以作为一个表示整数的单元来寻址,但它们也可以作为字节集合进行寻址。 The value of an int depends on the number of bytes that you set, and on the order of these bytes in CPU's interpretation of integers. int的值取决于您设置的字节数,以及CPU对整数的解释中这些字节的顺序。

It looks like your system stores the least significant byte at a lowest address, so the result of storing 1 and 2 at offsets zero and one produces this layout: 看起来你的系统将最低有效字节存储在最低地址,因此将12存储在偏移0和1的结果产生这种布局:

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

Integer value can be computed as follows: 整数值可以如下计算:

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

By taking x , which is a char * , and pointing it to the address of a , which is an int , you can use x to modify the individual bytes that represent a . 通过取x (它是一个char * )并将其指向a的地址(即int ,可以使用x来修改表示a的各个字节。

The output you're seeing suggests that an int is stored in little-endian format, meaning the least significant byte comes first. 您看到的输出表明int以little-endian格式存储,这意味着最不重要的字节首先出现。 This can change however if you run this code on a different system (ex. a Sun SPARC machine which is big-enidan). 但是,如果您在另一个系统上运行此代码(例如,大型enidan的Sun SPARC计算机),则可能会发生这种情况。

You first set a to 512. In hex, that's 0x200 . 首先将a设置为512.在十六进制中,即0x200 So the memory for a , assuming a 32 bit int in little endian format, is laid out as follows: 因此,假设以小端格式表示32位int a的内存布局如下:

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

Next you set x[0] to 1, which updates the first byte in the representation of a (in this case leaving it unchanged): 接下来将x[0]设置为1,这将更新a表示中的第一个字节(在这种情况下保持不变):

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

Then you set x[1] to 2, which updates the second byte in the representation of a : 然后将x[1]设置为2,这将更新a表示中的第二个字节:

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

Now a has a value of 0x201, which in decimal is 513. 现在a的值为0x201,十进制为513。

Let me try to break this down for you in addition to the previous answers: 除了之前的答案之外,让我试着为你解决这个问题:

#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; 
}

Note that I wrote first byte and second byte. 请注意,我写了第一个字节和第二个字节。 Depending on the byte order of your platform and the size of an integer you might not get the same results. 根据平台的字节顺序和整数的大小,您可能得不到相同的结果。

Lets look at the memory for 32bit or 4 Bytes sized integers: 让我们看一下32位4字节大小的内存:

Little endian systems 小端系统

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

Now assigning 1 to the first byte and 2 to the second one leaves us with this: 现在为第一个字节分配1,为第二个字节分配2,这给我们留下了:

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

Notice that the first byte gets changed to 0x01 while the second was already 0x02 . 请注意,第一个字节更改为0x01而第二个字节已经是0x02 This new number in memory is equivalent to 513 on little endian systems. 内存中的这个新数字相当于小端系统上的513

Big endian systems 大端系统

Lets look at what would happen if you were trying this on a big endian platform: 让我们看一下如果你在一个大端平台上尝试这个会发生什么:

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

This time assigning 1 to the first byte and 2 to the second one leaves us with this: 这次将1分配给第一个字节,将2分配给第二个字节给我们留下:

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

Which is equivalent to 16,908,800 as an integer. 相当于16,908,800整数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM