Casting int pointer to char pointer causes loss of data in C?

后端 未结 7 1998
梦如初夏
梦如初夏 2020-12-19 17:26

I have the following piece of code:

#include 
#include 
int main(int argc, char *argv[])
{
  int n = 260; 
  int *p = &n;
         


        
相关标签:
7条回答
  • 2020-12-19 17:44

    You're apparently working on a little-endian machine. What's happening is that you're starting with an int that takes up at least two bytes. The value 260 is 256+4. The 256 goes in the second byte, and the 4 in the first byte. When you write 0 to the first byte, you're left with only the 256 in the second byte.

    0 讨论(0)
  • 2020-12-19 17:52

    The int 260 (= 256 * 1 + 4) will look like this in memory - note that this depends on the endianness of the machine - also, this is for a 32-bit (4 byte) int:

    0x04 0x01 0x00 0x00
    

    By using a char pointer, you point to the first byte and change it to 0x00, which changes the int to 256 (= 256 * 1 + 0).

    0 讨论(0)
  • 2020-12-19 17:53

    I understood what exactly happens by changing value:

    #include <stdio.h>
    #include <stdlib.h>
    
    int main(int argc, char *argv[])
    {
      int n = 260; 
      int *p = &n;
      char *pp = (char*)p;
      *pp = 20;
    
        printf("pp = %d\n", (int)*pp);
      printf("n = %d\n", (int)n);
      system("PAUSE");  
      return 0;
    }
    

    The output value are 20 and 276

    So basically the problem is not that you have data loss, is that the char pointer points only to the first byte of the int and so it changes only that, the other bytes are not changed and that's why those weird value (if you are on an INTEL processor the first byte is the least significant, that's why you change the "smallest" part of the number

    0 讨论(0)
  • 2020-12-19 17:53

    Your problem is the assignment *pp = 0; You're dereferencing pp which points to n, and changing n. However, pp is a char pointer so it doesn't change all of n which is an int. This causes the binary complications in the other answers.

    0 讨论(0)
  • 2020-12-19 17:55

    In terms of the C language, the description for what you are doing is modifying the representation of the int variable n. In C, all types have a "representation" as one or more bytes (unsigned char), and it's legal to access the underlying representation by casting a pointer to char * or unsigned char * - the latter is better for reasons that would just unnecessarily complicate things if I went into them here.

    As schnaader answered, on a little endian, twos complement implementation with 32-bit int, the representation of 260 is:

    0x04 0x01 0x00 0x00
    

    and overwriting the first byte with 0 yields:

    0x00 0x01 0x00 0x00
    

    which is the representation for 256 on such an implementation.

    C allows implementations which have padding bits and trap representations (which raise a signal/abort your program if they're accessed), so in general overwriting part but not all of an int in this way is not safe to do. Nonetheless, it does work on most real-world machines, and if you instead used the type uint32_t, it would be guaranteed to work (although the ordering of the bits would still be implementation-dependent).

    0 讨论(0)
  • 2020-12-19 18:00

    Considering 32 bit systems, 256 will be represented in like this.

    00000000 (Byte-3)   00000000 (Byte-2)    00000001(Byte-1)     00000100(Byte-0)
    

    Now when p is typecast-ed to a char pointer, the label on the pointer changes, but the memory contents don't. It means earlier p could have access 4 bytes, as it was an integer pointer, but now it can only access 1 byte as it is a char pointer. So, only the LSB gets changes to zero, not all the 4 bytes.

    And it becomes

    00000000 (Byte-3)   00000000 (Byte-2)    00000001(Byte-1)     00000000(Byte-0)
    

    Hence, the o/p is 256.

    0 讨论(0)
提交回复
热议问题