在 C 中使一个指针指向另一个指针所指向的内容
我无法在标题中真正描述我的问题,但基本上我需要一些指针算术方面的帮助。假设您有一个如下所示的结构。然后你会得到一个指向内存结构中 long 后面的指针。假设指针是*p。所以我会做 p += sizeof(void *) 来获取下一个指针位置的 p 。现在,我如何真正使 p 指向 next 所指向的内容,而不仅仅是让它指向内存中下一个指针的位置?
struct freeblock {
long s;
// <--- THE POINTER WOULD BE POINTING HERE
struct freeblock *prev;
struct freeblock *next;
}
I couldn't really describe my problem in the title, but basically I need some help with pointer arithmetic. Lets say you have a struct like following. Then you get a pointer to after the long in the struct in memory. Lets say the pointer is *p. so I would do p += sizeof(void *) to get p at the location of the next pointer. Now how do I actually make p point to what next points to rather than just have it point to where the next pointer is in memory?
struct freeblock {
long s;
// <--- THE POINTER WOULD BE POINTING HERE
struct freeblock *prev;
struct freeblock *next;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
这可能是一个棘手的问题。您确实不想在结构中进行指针算术。原因是结构对齐。如果你有一个像这样的结构,会发生什么:
y 不会在 x 之后的一个字节开始。为了保持对齐,y 从 4 的倍数的地址开始,在 x 之后添加一些填充字节。
如果你有一个结构实例 0x08 的地址并添加一个 char 的大小,产生 (0x09),你将不会得到 y 0x12 的开头,你会得到一些垃圾数据,一部分是垃圾,一部分是 y。
在这种情况下,您应该没问题,因为相同的类型是一个接一个的,您可以这样做:
您确实想要获得一个指向结构的指针,并让编译器为您计算偏移量。
This has the potential to be a tricky question. You really don't want to be doing pointer arithmetic in your structs. The reason is Struct Alignment. What happens is if you have a struct like so:
y is not going to start one byte after x. To preserve alignment, so y starts on, say, an address that's a multiple of 4, there will be some padding bytes added after x.
If you have the address of a struct instance 0x08 and add the size of a char, yielding (0x09) you won't get the start of y 0x12, you'll get some garbage data that's part junk and part y.
In this case you should be OK as the same types are right after one another and you can do something like so:
You really want to get a pointer to the struct and let the compiler compute the offsets for you.
试试这个:
p1 指向与 next 相同的位置。
一点解释 - 指针在 C 中类型化。向指针添加 1 意味着将 sizeof(type) 添加到实际地址,因此您需要将指针带到正确的类型,或者如果您想要手动算术,则将指针带到 char * ,因为 sizeof(字符)为 1。
Try this:
p1 points to the same place as next.
Little explanation - pointers are typed in C. Adding 1 to a pointer means adding sizeof(type) to the actual address, so you need to bring the pointer to a proper type, or to char * if you want manual arithmetics, since sizeof(char) is 1.
假设您只知道
p
的当前值,并且它指向struct freeblock
实例的prev
字段。同时,请记住,“long 之后”地址可能与prev
字段的地址不同,例如,如果sizeof(long)==4
和指针对齐8 个字节(对于某些 64 位平台来说是这样);请参阅 Paul Rubel 的回答以获取解释。现在您需要在同一实例中获取
next
的值,并取消引用它。符合标准的解决方案可能应该涉及offsetof()
宏:首先借助
offsetof()
计算prev
和next
字段的地址之间的差异,然后转换p
到指针到字符以便正确添加增量并获取下一个字段的地址,然后将其转换为指针到指针到空闲块,取消引用该地址以获得所需的值,最后将值分配给p
并强制转换为指向 void 的指针(可以省略,但我会将其保留在生产代码中)。Let's assume that you only know that the current value of
p
, and that it points to aprev
field of astruct freeblock
instance. Meanwhile, remember that the "after the long" address may not be the same as the address ofprev
field, e.g. ifsizeof(long)==4
and pointers are aligned at 8 bytes (which is true for some 64-bit platforms); see Paul Rubel's answer for explanation.Now you need to get the value of
next
in the same instance, and dereference it. A standard-compliant solution should probably involveoffsetof()
macro:So you first calculate the difference between addresses of
prev
andnext
fields with help ofoffsetof()
, then castp
to pointer-to-char in order to correctly add the delta and get the address ofnext
field, then cast it to pointer-to-pointer-to-freeblock, dereference that address to get the desired value, and finally assign the value top
with casting to pointer-to-void (which can be omitted, but I would keep it in production code).指针应指向特定类型变量,不能对
void*
执行 aritmethic 操作。但假设它是某种有效的数据类型,则
p++
或p += 1
将完成这项工作,请注意,开始将指针强制转换为不同类型是危险的。p+=1; // 就像 d += 1*sizeof(int);
Pointer should point to a specific type variable, you cannot perform aritmethic actions on
void*
.But assuming it is some valid data type, then
p++
orp += 1
will do the job, note that it is dangerous to start casting pointer to different types.p += 1; // just like d += 1*sizeof(int);
你说“p 在
next
指针的位置”并且你想“让 p 指向next
指向的位置”:我将假设 < code>p 是一个
char*
:简要说明:
由于
p
指向next
,因此p
code> “充当”指向struct freeblock*
或struct freeblock**
的指针。要获取 struct freeblock** 所指向的值,只需取消引用它(产生另一个指针,但类型错误)。将生成的指针转换为p
的正确类型,然后就完成了。You say that "p at the location of the
next
pointer" and you want to "make p point to whatnext
points to":I'm going to assume that
p
is achar*
:A brief explanation:
Since
p
is pointing atnext
,p
is 'acting' as a pointer to astruct freeblock*
, or astruct freeblock**
. To get the value of what thatstruct freeblock**
is pointing to, you simply dereference it (resulting in another pointer, but of the wrong type). Cast that resulting pointer to the right type forp
and you're set.也许您正在尝试取消引用 p,如下所示:
请注意,我选择保持我的意识,即 x 的类型与 p 的类型不同。您可以将 x 和 p 都声明为 void *,但是您必须将 x 强制转换为“((struct freeblock *)x)”,然后才能访问这些字段。
由于编译器对齐问题等,这不能保证有效。这无疑是一种糟糕的代码设计方式。
Maybe you are trying to dereference p, like this:
Note that I have chosen to maintain my awareness that the type of x is different than the type of p. You could declare x and p both as void *, but you would have to cast x to '((struct freeblock *)x)' before you could get at the fields.
This is not guaranteed to work, due to compiler alignment issues, etc. Certainly a terrible way to design your code.