代码之家  ›  专栏  ›  技术社区  ›  whacko__Cracko

这个指针算法是如何工作的?

  •  3
  • whacko__Cracko  · 技术社区  · 16 年前
    #include <stdio.h>
    
    int main(void){
      unsigned a[3][4] = {
        {2,23,6,7},
        {8,5,1,4},
        {12,15,3,9}
     };
     printf("%u",*((int*)(((char*)a)+4)));
     return 0;
    }
    

    a[0][1]

    编辑:回滚到旧版本 yucky 代码,正是呈现给我的:P

    5 回复  |  直到 16 年前
        1
  •  13
  •   GManNickG    16 年前

    2, 23, 6, 7, 8...
    

    这样做的目的是将数组强制转换为 char* ,它允许您访问单个字节,并指向此处:

    2, 23, 6, 7, 8...
    ^
    

    然后,它添加四个字节,将其移到下一个值(稍后将对此进行详细介绍)。

    2, 23, 6, 7, 8...
       ^
    

    然后它把它变成了一个 int* 然后取消对它的引用,得到值23。


    从技术上讲,此代码有三个方面存在错误。

    unsigned 大小为4字节(因此 + 4 ). 但这不一定是真的!最好是 + sizeof(unsigned) ,确保正确性,无论大小

    第二个问题是演员阵容 int :原始数组为 未签名 ,但该值正被转换为 int . 中存在值 未签名 int 无法表示(因为在 范围的一半在负数中。)因此,如果数组中的一个值不能表示为 int INT_MAX ),则会得到错误的值。最好改成 unsigned*

    最后一件事是格式说明符。整数的说明符是 %d ,但代码使用 %u ,表示无符号整数。事实上,即使铸造回到 错了,, printf 他将要出演 将价值返回到 未签名* ,恢复它的完整性。通过解决问题二,问题三就能解决问题本身。

    有一个 第四个问题:代码很糟糕。这可能是为了学习,但是 讨厌

        2
  •  9
  •   paxdiablo    16 年前

    阵列:

    unsigned a[3][4] = {
        {2,23,6,7},
        {8,5,1,4},
        {12,15,3,9}
    };
    

    在内存中的布局为(假设 a 它本身位于内存位置 0x8000 ,一种特殊的尾数形式,对于四字节 int

    0x8000  0  0  0  2
    0x8004  0  0  0 23
    0x8008  0  0  0  6
    0x800C  0  0  0  7
    0x8010  0  0  0  8
    0x8014  0  0  0  5
    0x8018  0  0  0 14
    0x801C  0  0  0 12
    0x8020  0  0  0 15
    0x8024  0  0  0  3
    0x8028  0  0  0  9
    

    分解表达式:

    *((int*)(((char*)a)+4))
    
    • ((char*)a) 给你一个 char 指针。
    • +4 将该指针提前4个字节( 4 * sizeof(char)
    • (int*) 将结果返回到 int 指针。
    • * 取消引用该指针以提取 int

    这是一种非常愚蠢的方法,因为它本质上是不可移植的(对于 例如,是两个或八个字节)。

        3
  •  2
  •   Tronic    16 年前

    它首先隐式地将数组a转换为指向其开头的指针。然后它将指针强制转换为char*并将值递增4。值4恰好与系统上的sizeof(unsigned)相同,因此实际上它从一开始就向前移动了一个元素n。然后它将地址强制转换为int*并读取它所指向的值(运算符*)。此结果值打印为无符号整数,这是因为int和unsigned的大小相同。

    内存中静态2D数组的布局是这样的,所有元素实际上都以一维数组的顺序存储。

        4
  •  1
  •   Fakrudeen    16 年前

    它可以容纳4个字符,每个字符是一个字节[在C语言中不是在Java/C语言中,等等]。

    数组在内存中连续分配。将无符号数组视为char*时,需要将指针移动4步才能到达数组中的下一个无符号值。

        5
  •  1
  •   flashnik    16 年前

    首先,创建一个大小为3x4的2维阵列。

    之后 ((char*)a) 您可以将其作为字符数组使用。让我们把它指定为b。

    ((char*)a)+4 b[4] ,它指向 5

    将数组转换回int时, i-th i*4 字节if sizeof(int) = 4