有人可以向我解释一下,以下两行代码中发生了什么?假设我们正在使用32位机器
p - 是指针
(*(long *)((char **)(p) - 1))
(*(int *)((int)(p) - 4))
我唯一理解的是,*(long *)
将“某些东西”转换为long
类型的指针,然后是deref。获得价值。
谢谢!
答案 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));
(char **)(p)
会为您提供[0] [0]>>>>的地址即1000 (char **)(p) + 1
会将sizeof int添加到您的地址>>>>即1004 (*(long *)((char **)(p) + 1));
将评估为