【问题标题】:Regarding dereferencing 'void *' pointer关于取消引用'void *'指针
【发布时间】:2017-11-03 20:40:45
【问题描述】:

我不知道如何从下面的代码行中删除上述警告。数据是空指针,作为回调函数的一部分,将在数据指针中接收字符串。因为我已经对 void 指针进行了类型转换,但编译器仍然显示警告。

下面一行基本上显示了两个警告。 1.取消引用'void *'指针 2.取'void'类型表达式的地址

 service_ind = atoi((const char*)&data[at_response.param[0].start_of_value_index]) ? TRUE:FALSE ;

以下是必填信息

void * data;
AT_PARSER_RESPONSE at_response;

typedef struct
{

/*Other parameters */

AT_PARAM  param[AT_MAX_NUM_PARAM];

}AT_PARSER_RESPONSE

【问题讨论】:

  • 请给出dataat_response以及at_response.param[0]的任何类型的定义。
  • 我在想(仍然是我的第一杯咖啡)优先顺序不是您对(const char*)&data[at_response.param[0].start_of_value_index] 的想法(即您可能需要额外的括号),或者您需要转换@987654327在使用[] 之前将@ 转换为有效类型,具体取决于data 真正 是什么。

标签: c pointers void-pointers dereference


【解决方案1】:

引用C11,第 6.5.3.2 章:

一元* 运算符表示间接。如果操作数指向一个函数,则结果为 功能指示符;如果它指向一个对象,则结果是一个左值,指定 目的。如果操作数的类型为“类型指针”,则结果的类型为“类型”。 如果 无效值已分配给指针,一元 * 运算符的行为是 未定义。

所以,您的代码导致undefined behavior

另外,相关的,来自第 §6.2.5 章:

void 类型包含一组空值; 这是一个不完整的对象类型 无法完成。

因此,指向void 的指针是一个无效的解引用操作数。


一个可能的实际案例和可能的解决方案

有时,为了创建泛型,我们将某个指针转换为void *,将其作为参数传递给函数,然后在函数内部,根据一些已知信息将其转换回原始类型。根据第 6.3.2.3 章,这是完全有效的:

[...] 指向的指针 任何对象类型都可以转换为指向 void 并再次返回的指针;结果应 比较等于原始指针。

如果这是你的情况,并且你在函数内部取消引用,你可以将指针转换为任一

在取消引用之前。

【讨论】:

  • @CIsForCookies 正如我所提到的,它来自 C11 标准,实际已售出,但您可以在线获得一些非常准确的草稿版本。 :)
  • 但是,您可以在取消引用之前将指针转换为有效类型。 这也可能是未定义的行为,因为它可以violate strict aliasing,例如,如果您从char *,将其分配给 void *,然后将其转换为 double * 并尝试取消引用它。
  • @CIsForCookies-- herehere
  • 我想你的意思是@AndrewHenle——我只是为 CisForCookies 提供了几个链接
  • @CIsForCookies 另一种方式也是,除了转换为[unsigned] char *。根据the standard指向对象类型的指针可以转换为指向不同对象类型的指针。如果生成的指针未针对引用的类型正确对齐,则行为未定义。否则,当再次转换回来时,结果将等于原始指针。当指向对象的指针转换为指向字符类型的指针时,结果指向对象的最低寻址字节。