使用char指针更改int值

时间:2018-03-19 08:03:13

标签: c pointers casting

为什么此代码打印10 = -246而不是10 = 10?指针大小是否重要?

#include <stdio.h>

int main() {
    int i = 10;
    int j = -1;

    char *p, *q;

    p = (char*) &i;
    q = (char*) &j;

    *q = *p;

    printf("%d = %d\n", i, j);

    return 0;
}

5 个答案:

答案 0 :(得分:1)

首先,此处的结果取决于CPU的endianess。你似乎有一个小端CPU。

假设int是32位2的补码,-10xFFFFFFFF的形式存储在4个字节中。 char访问仅影响一个字节。由于你有小端,它将是你的情况下最不重要的字节。该字节将被值10,0x0A覆盖。最终得到0xFFFFFF0A,它是-246的2的补码表示。

请注意char类型具有实现定义的签名,因此在进行位/字节操作时应始终避免使用。请改用uint8_t

另请注意,在特定情况下使用字符类型(uint8_t是字符类型)时,通过不同类型的指针访问一种数据类型是有风险且定义不明确的,因为它们是“严格的别名规则“。

答案 1 :(得分:1)

  

指针大小是否重要?

不,指针的大小无关紧要。什么是指针的类型,即它指向的类型。

通过指针分配时复制的字节数取决于指针类型。如果指针类型是char指针,它将复制sizeof(char)个字节。如果指针类型是int指针,它将复制sizeof(int)个字节。

  

为什么此代码打印10 = -246而不是10 = 10?

它取决于系统。由于得到这个结果,你可能在一个小端系统上,这意味着内存中的数据首先以LSB存储(即指向变量的指针指向该变量的LSB)。

那么代码中发生的是变量i的LSB被复制到变量j的LSB。由于sizeof(int)超过1,因此您不会在ij相等的情况下结束。仅仅因为您没有将i的所有字节都复制到j

假设32位int,它可能看起来像:

enter image description here

答案 2 :(得分:0)

假设CPU为32位。

第一个问题:为什么要打印10 = -246

i = 10;  (0x0000 000A)
j = -1;  (0xFFFF FFFF) Two's Complement

* q指向整数j的最低8位,在*q = 10;之后,j变为0xFFFF FF0A,这是-246

的两个补码

参考How Computers Represent Negative Binary Numbers?

第二个问题:指针大小是否重要?

是的,在这种情况下,指向char指针的covert int指针将丢失24位数据。

答案 3 :(得分:0)

这里p&amp; q是一个char指针。 p =(char *)&amp; i;所以p将指向整数var i的第一个字节,它是4个字节。所以在解除p时你会得到10(00001010)。

q =(char *)&amp; j;当j = -1时,它是最大的负数。这意味着j var将在32位中全部为1(11111111 11111111 11111111 11111111)

* q = * p;在这一行中,您将最低的第一个字节(00001010)从i的位置复制到j的位置第一个字节,因为两个指针都是char *。所以现在复制后,j的位置值将为: 11111111 11111111 11111111 00001010相当于-246。计算11111111 11111111 11111111 00001010的2的补码。它会给你-246。

答案 4 :(得分:0)

您必须进行这样的转换才能使j中的i值为: * (int*)p = * (int*)q 它将转换指针的类型,您将“转移” i在j中的值。

或者另外,您也可以不使用for循环而进行强制转换: `

for(int k=0; k<sizeof(int);k++){
    *(p+k) = *(q+k);
}

` 通过此循环,您将一次将k的每个字节中的i的每一位写入一个字节。这是因为int具有4字节结构,而char具有1字节结构。