如何在C中取消引用和自动增量转换指针?

时间:2016-01-19 23:52:09

标签: c pointers casting

我在普通C中有一个void*,我在浏览一些非结构化数据时正在使用它,并且我想在我去的时候使用dereference和autoincrement进行投射。我想写下以下内容:

void* ptr = /*something*/;
uint16_t i = *((uint16_t*) ptr)++;

编译器对象并告诉我“左值作为递增操作数”,但我想我认为指针作为指针仍然可以作为左值。

显然,我的意图是让ptr现在指向超出之前指向的两个字节。我无法删除围绕ptr转换的括号,因为++的优先级高于强制转换,所以这不会像我想要的那样工作:

int i = *(uint16_t*) ptr++;

我当然可以做自己的增量,如下所示,但我希望有一些优雅和简洁的东西:

int i = *(uint16_t) ptr;
ptr += sizeof(uint16_t);

这样做的好方法是什么?

2 个答案:

答案 0 :(得分:1)

写起来最简单:

uint16_t *uptr = ptr;
uint16_t i = *uptr++;
ptr = uptr;            // if required

您可以重新构建较大的代码,以尽可能多地使用uint16_t *,从而无需进行如此多的转换。

答案 1 :(得分:0)

长时间不允许将指针强制转换为其他类型,可能是自C89以来。原因是从一种指针到另一种类型的转换可以改变表示,因此可能不会引用同一个对象。

您必须将表达式拆分为2个语句:

void *ptr = /*something*/;
uint16_t i = *(uint16_t*)ptr;
ptr = (uint16_t*)ptr + 1;

或者,如果单个表达式的上下文命令,您可以使用此hack:

uint16_t i = ((uint16_t*)(ptr = (uint16_t*)ptr + 1))[-1];

或者如果你想混淆更多这个:

uint16_t i = (-1)[(uint16_t*)(ptr = (uint16_t*)ptr + 1)];