指针算术问题

时间:2010-12-16 05:45:57

标签: c++ c

有人可以向我解释一下,以下两行代码中发生了什么?假设我们正在使用32位机器

p - 是指针

(*(long *)((char **)(p) - 1))
(*(int *)((int)(p) - 4))

我唯一理解的是,*(long *)将“某些东西”转换为long类型的指针,然后是deref。获得价值。

谢谢!

5 个答案:

答案 0 :(得分:1)

    (*(long *)((char **)(p) - 1))

    Looks like getting the length of some kind of length byte character array 
that was passed by reference. But that is just first glance..

    (p) = some object

    (char **) casts some object to the address of the address of a character, which is a 32bit value sizeof(char**)

    -1 gets the 32bits in memory prior to (char **)(p)
    *(long*) does what you thought, takes that 32bits, casts it as a long *, and dereferences it.
    So there is a record in memory like: 

    struct {long * n; char ** s;  } 
    similiar to what happens in parameter passing.

(*(int *)((int)(p) - 4))

这个更丑陋。一些对象p被强制转换为int,让我们只希望sizeof(int)为32,所以它可能是一个地址,从中减去4(地址仍在计数字节,4个字节是32位)转换为指向int的指针,并取消引用它。

要获得额外信用,请将其与:  *((int *)((int)(p)) - 1)

答案 1 :(得分:1)

(*(long *)((char **)(p) - 1))

从指针p开始。将其转换为类型(char **)。从中减去一个。将结果转换为类型(long *),然后取消引用结果。换句话说,将指针移位一个字节,并获得存储在该地址的long值。在某些平台上可能会破坏此操作,尤其是取决于p的类型。

(*(int *)((int)(p) - 4))

从指针p开始。将它转换为int。减去4.将其转换为(int *),并取消引用结果。现在,您不是使用普通的指针算法,而是直接将指针值作为整数,将其移动4,并读取结果指向的int。某些系统也会破坏此操作。

我认为我设法解析了这一点而不会迷失在parens中。无论如何,不​​要这样做。这是病态的。可能有一些奇怪的嵌入式开发任务,你认为这样的事情是个好主意。如果是这样,永远不要承认已经做到了。如果被发现,就把它归咎于其他人。

例如,对于第二个示例,p为int *,在具有8位字符和32位int的系统上,您基本上正在完成*(p-1)

OTOH,在16位int的机器上,你正在做*(p-2),而在64位int的机器上,你正在做*(p-0.5),这是不合理的,只是在抱怨未对齐的内存访问时可能会崩溃。 (并且它应该崩溃。)使用实际指向正确类型的指针,你永远不应该有理由做这种废话。

答案 2 :(得分:1)

1: ((char **)(p) - 1):将p转换为指向chars和subtract数组的数组(所以它现在就像& p [-1])

(long *):将它转换为指向long的指针,并从该地址开始持续很长时间。

2: ((int)(p) - 4):将p转换为int并减去4

(int *):将其强制转换为指向int的数组,并从该地址获取int

答案 3 :(得分:1)

首先在p之前很久 对于x32 sizeof(char *)== sizeof(long),所以(long *)(char * )是(long
所以它只是*( (long*)p - 1 )((long*)p)[-1]

第二行也是如此,但它会产生int而不是long(long*)p - 1(int)p - 4的地址相同,因为sizeof(long)== 4.

答案 4 :(得分:1)

考虑p是指向二维数组的指针 .eg

int a[][5] = {10,20,30,40,50,11,21,31,41,51,12,22,32,42,52,13,23,33,43,53,14,24,34,44,54};
int (*p)[5] = a;

现在为了简单起见,我们假设[0] [0]的地址为1000

现在让我们评估(*(long *)((char **)(p) + 1));

  1. (char **)(p)会为您提供[0] [0]>>>>的地址即1000
  2. (char **)(p) + 1会将sizeof int添加到您的地址>>>>即1004
  3. (*(long *))将获取地址1004处的值,在我们的示例
  4. 中为20 在我们的案例中,

    (*(long *)((char **)(p) + 1));将评估为

相关问题