我正在尝试使用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)
答案 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)
是大多数编译器的编译器,对于这些编译器,它是可移植的。