【问题标题】:What is the purpose of void *array = *(void **) member + siz * (*p_n);void *array = *(void **) member + siz * (*p_n); 的目的是什么?
【发布时间】:2014-10-21 13:52:52
【问题描述】:

我正在尝试使用 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)

【问题讨论】:

  • 看起来它被设计成人类无法阅读的。 :)
  • 有些编译器将 void* 与 BYTE* 类似,至少在指针运算中如此。即 sizeof(void*) 编译为 1。我会将这条杂乱的线拆分为它的元素,并将 void* 替换为 char* 用于指针算术的特定目的
  • @harper 如果代码“整理”后会读到什么
  • 一个好的执行方法是让您使用它的char 版本并使用临时变量一个接一个地定义相同的计算。 void* 版本只是 gcc'ish 垃圾。 void* 算术是一个没有多大意义的扩展。

标签: c protocol-buffers c99 c89


【解决方案1】:

作为member 传递的参数是指向char 指针的指针的地址。首先 cast 和 defererence 得到那个指针。(传递指针的地址,以便可以在函数中更改指针。)

添加siz * (*p_n) 增加指向正确元素的指针。

整行可以改写为:

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

进行了从 void* 到 char* 的更改,以便可以进行指针运算,因为 C 标准不允许在 void 指针上使用它。错误消息告诉您, void* 指向的对象的大小未知,因此您必须使用 char* 指针。

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

【讨论】:

    【解决方案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) 是大多数编译器的一种,对于这些编译器来说它是可移植的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-11-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-09-16
      • 2023-03-16
      • 1970-01-01
      相关资源
      最近更新 更多