我无法在标题中描述我的问题,但基本上我需要一些指针算法的帮助。假设你有一个像下面这样的结构。然后你得到一个指针,指向内存中结构中的long。让我们说指针是 * p 。所以我会做 p + = sizeof(void *)来得到p在下一个指针的位置。现在,我如何实际指向下一个指向的内容,而不仅仅指向下一个指针在内存中的位置?
struct freeblock {
long s;
// <--- THE POINTER WOULD BE POINTING HERE
struct freeblock *prev;
struct freeblock *next;
}
答案 0 :(得分:2)
试试这个:
void *p; /* points to prev now */
struct freeblock *p1;
p = ((char *)p)+sizeof(struct freeblock *); /* advance p to next */
p1 = *(struct freeblock **)p; /* take whatever is in next */
p1指向下一个相同的位置。
很少解释 - 在C中键入指针。在指针中添加1意味着将sizeof(type)添加到实际地址,因此您需要将指针指向正确的类型,或者如果您需要手动算术,则需要指向char *,因为sizeof(char)是1。
答案 1 :(得分:2)
这有可能是一个棘手的问题。你真的不想在你的结构中做指针运算。原因是Struct Alignment。如果您有这样的结构,会发生什么:
struct a{
char x; //address 0x8
//potentially 3 bytes lost here:
int y; //address 0x12
}
y在x之后不会开始一个字节。为了保持对齐,所以y开始,例如,地址是4的倍数,在x之后会添加一些填充字节。
如果你有一个结构实例0x08的地址并添加一个字符的大小,产生(0x09)你不会得到y 0x12的开头,你会得到一些垃圾数据&#39 ; s部分垃圾和部分y。
在这种情况下你应该没问题,因为相同的类型是相继的,你可以这样做:
freeblock* p = s.prev;
p += sizeof(p);
freeblock next = *p;
你真的想得到一个指向结构的指针,让编译器为你计算偏移量。
答案 2 :(得分:1)
假设您只知道p
的当前值,并且它指向prev
实例的struct freeblock
字段。同时,请记住“长时间”地址可能与prev
字段的地址不同,例如如果sizeof(long)==4
和指针对齐为8个字节(即true for some 64-bit platforms);请参阅Paul Rubel的解释答案。
现在您需要在同一个实例中获取next
的值,然后取消引用它。符合标准的解决方案应该涉及offsetof()
macro:
void * p;
...
size_t delta = offsetof(struct freeblock,next)-offsetof(struct freeblock,prev);
p = (void*) *(struct freeblock**)((char*)p+delta);
因此,您首先在prev
的帮助下计算next
和offsetof()
字段的地址之间的差异,然后将p
转换为指向char的指针以便正确添加delta并获取next
字段的地址,然后将其转换为指向指针到freeblock的指针,取消引用该地址以获得所需的值,最后将值赋给p
转换为指向void的指针(可以省略,但我会将其保留在生产代码中)。
答案 3 :(得分:0)
也许你正试图取消引用p,就像这样:
char *p;
struct freeblock *x;
// you got the value for p here somehow.
x = *((struct freeblock **)p);
// now you can access the fields:
if (x->next != 0)
{ //...
}
请注意,我选择保持我的意识,即x的类型与p的类型不同。你可以将x和p都声明为void *,但是你必须先将x转换为'((struct freeblock *)x)'才能进入字段。
由于编译器对齐问题等原因,这无法保证正常工作。当然,这是设计代码的一种可怕方法。
答案 4 :(得分:0)
指针应指向特定的类型变量,您无法对void*
执行aritmethic操作。
但假设它是一些有效的数据类型,那么p++
或p += 1
将完成这项工作,请注意,开始将指针指向不同类型是危险的。
struct a{
long s;
int d;// <--- THE p POINTER WOULD BE POINTING HERE
struct freeblock *prev;
struct freeblock *next;
}
p + = 1; //就像d + = 1 * sizeof(int);
struct a{
long s;
int d;
struct freeblock *prev; // <--- now p points here
struct freeblock *next;
}
答案 5 :(得分:0)
你说“p在next
指针的位置”,你想“指出next
指向的地方”:
我将假设p
是char*
:
p = (char*) *((struct freeblock**) p);
简要说明:
由于p
指向next
,p
正在“充当”指向struct freeblock*
或struct freeblock**
的指针。要获取struct freeblock**
所指向的值,您只需取消引用它(导致另一个指针,但类型错误)。将结果指针转换为p
的正确类型,然后设置。