2010-12-16 116 views
1

有人可能会向我解释,在以下两行代码中发生了什么?假设我们在32位计算机上工作指针算术问题

p - 为指针

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

我了解的唯一的事情,就是*(long *)“东西”转换为long类型的指针,然后DEREF。获得价值。

谢谢!

+3

评估到20我就希望* *,这是一个32位的机器上。该代码是64位不安全的。 – 2010-12-16 05:48:24

+0

'p'是什么?[MoreCharactersToAppeaseJeffAtwood] – 2010-12-16 05:48:31

+0

根据'p'的类型可能是ub也可能不是ub。 – wilhelmtell 2010-12-16 05:48:52

回答

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

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

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

从指针p开始。将其转换为int。减去4.将它转换为(int *),并取消引用结果。现在,不是做正常的指针算术,而是直接将指针值作为整数进行摆动,将其移位四位,然后读取结果指向的int。该操作在某些系统上也会被打破。

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

例如,与第二实施例,其中p为一个int *,并用8个字符和32位整数的系统上,你基本上完成*(P-1)

OTOH,在一个一台16位int的机器,你正在执行*(p-2),并且在一台64位int的机器上,你正在执行*(p-0.5),这是不明智的,并且可能会崩溃而只是抱怨关于未对齐的内存访问。 (它应该会崩溃。)使用实际指向正确类型的指针,并且你永远不应该有理由去做这种无稽之谈。

+0

我刚刚注意到我的第一个描述是错误的。从char **减1会调整指针的sizeof(char *)而不是sizeof(char)。所以,如我所说,偏移量可能大于一个字符的大小。 (虽然从技术上来说,一个char可以和char *一样......) – wrosecrans 2010-12-16 07:48:39

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: ((字符**)(P) - 1):投p来指向字符的数组的数组和减去(所以它现在就像& P [-1])

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

2: ((int)的(P) - 4):投p存放和减去4

(INT *):投它指向INT的阵列,并从该地址

INT取
1

首先得到p之前很久。
对于X32的sizeof(字符*)==的sizeof(长),所以(长*)(字符* )为(长
所以它只是*((long*)p - 1 )((long*)p)[-1]

第二行则是相同的,但它产生int而不是long(long*)p - 1是相同的地址作为(int)p - 4,因为的sizeof(长)== 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. (*(长*))将获得价值在我们的例子中的地址1004是20

(*(long *)((char **)(p) + 1));将在我们的例子