void * array = *(void **)member + siz *(* p_n)的目的是什么?

时间:2014-10-21 13:52:53

标签: c protocol-buffers c99 c89

我正在尝试使用C90编译器(MS VS2012)编译protobuf-c示例。

在protobuf-c源代码中,有两个C99特定的东西可以很容易地改变为与C90兼容,即在范围中间的变量声明(not allowed in C90)和instantiation of structs来自. - 语法(例如some_struct_type name = {.a=1,.b=2})。

我现在遇到了一个编译错误。源文件'protobuf-c.c'中的相应行读取:

void *array = *(void **) member + siz * (*p_n);

member定义为void *p_n定义为size_t *。 并且相应的错误是

error C2036: 'void *' : unknown size

请注意,这对protobuf-c版本1.0.1有效(请参阅respective source code,第2404行)。此行已在版本1.0.2中更改为

void *array = *(char **) member + siz * (*p_n);

this comment。 因此更改行会消除编译错误。

我的问题是:

  • 我想了解这行代码。
  • 我可以切换到*(char **)版本吗?
  • 告诉我的错误信息是什么?

(出于其他原因,我想坚持使用protobuf-c 1.0.1)

2 个答案:

答案 0 :(得分:4)

传递为member

参数是指向char指针的指针的地址。首先,转换和引用得到指针。(指针的地址被传递,以便指针可以在函数中改变。)

添加siz * (*p_n)会将指针递增到正确的元素。

整行可以改写为:

char** pm = member ;
char* m = *pm ;
void *array = m + siz * (*p_n);

从void *到char *的更改使得指针算法成为可能,因为C Standard不允许在void指针上使用它。错误消息告诉你,void *指向的对象的大小是未知的,因为你必须使用char *指针。

只要传递给函数的对象具有类型char**,您就可以切换到char **版本。

答案 1 :(得分:2)

I would like to understand this line of code.

代码使指针算术并尝试隐藏细节。因此,在指针未被引用的任何地方都使用void。假设sizeof (*(void*))等于一。

Can I switch to the *(char **) version?

是的,因为代码会分配结果指针并且不会取消引用指针。

What is the error message telling me?

这个hack是特定于编译器的。你的编译器没有解决这个问题,它没有提供void*目标的大小。

你应该使用"便携式"版。 sizeof(char)是大多数编译器的编译器,对于这些编译器,它是可移植的。