【问题标题】:how to dereferenze a void* as array of void*如何将 void* 取消引用为 void* 数组
【发布时间】:2014-04-29 20:44:02
【问题描述】:

我想构建一个结构,它可以保存简单的数据类型,如该结构的整数或数组。

结构如下:

typedef struct data_s {
  size_t size;  // size of memory data is pointing to
  void * data;  // pointer to data (array of data_t or simple type)
} data_t;

我已经简化了,通常结构中存储的信息更多。
我编写了设置和获取整数值的函数,它们可以工作!
现在我尝试编写用于创建数组以及设置和获取值的函数,但它们不起作用。
我用 gdb 找到它失败的地方。它向我表明我的取消引用没有按我的预期工作。我使用以下内容:

((data_t**)(data->data))[i]

我遇到了访问冲突。

如果有人能告诉我我的错误,那就太好了。这是一个工作代码示例,我已经最小化了代码,你没有我的程序的开销(也删除了错误处理)。

在带有 3.11 内核的 xubuntu 13.10 上使用带有 gcc 4.8.1 的 gcc -g main.c -o test 编译代码没有任何错误

#include <stdio.h>
#include <stdlib.h>

typedef struct data_s {
  size_t size;
  void * data;
} data_t;

void set_integer(data_t *data, int value){
  data->size = sizeof(int);
  data->data = malloc(data->size);
  *((int*)(data->data)) = value;
}

void get_integer(data_t *data, int *value){
  (*value) = *((int*)(data->data));
}

void create_array(data_t *data, size_t len){
  data->size = sizeof(data_t) * len;
  data->data = malloc(data->size);
  int i;
  for(i=0; i<data->size; i++){ //initialize array
    ((data_t**)(data->data))[i]->data = NULL;  
    ((data_t**)(data->data))[i]->size = 0;
  }
}

void set_array(data_t *data, int index, data_t *value){
  ((data_t**)(data->data))[index]->data = value->data;
  ((data_t**)(data->data))[index]->size = value->size;
}

void get_array(data_t *data, int index, data_t *value){
  value->data = ((data_t**)(data->data))[index]->data;
  value->size = ((data_t**)(data->data))[index]->size;
}

void free_data(data_t *data, int is_array){
  if(is_array){
    int i;
    for(i=0; i<(data->size / sizeof(data_t)); i++)
      free(((data_t**)(data->data))[i]->data);
  }
  free(data->data);
}

int main(int argc, char**argv){

  data_t data;
  set_integer(&data, 42);
  int val;
  get_integer(&data, &val);
  printf("expect 42; has: %d\n", val);
  free_data(&data, 0);

  data_t element;
  create_array(&data, 3);
  int i;
  for(i=0; i<3; i++){
    set_integer(&element, i*2);
    set_array(&data, i, &element);
  }
  for(i=0; i<3; i++){
    get_array(&data, i, &element);
    get_integer(&element, &val);
    printf("index: %d; value: %d\n", i, val);
  }
  free_data(&data, 1);

  return 0;
}

【问题讨论】:

  • 您将结构成员和结构变量都命名为data,从而增加了混乱。

标签: c arrays struct void-pointers


【解决方案1】:

((data_t**)(data-&gt;data))[i]在data->data是指针数组时使用,试试

((data_t*)(data->data))[i]

EDIT:要访问成员,请使用类似

((data_t*)data->data)[i].data = NULL;
((data_t*)data->data)[i].size = 0;

【讨论】:

  • 它无法编译,因为我无法再将它作为数组访问,我猜它必须是 ** 之类的东西
  • 我已经添加了额外的代码来访问结构变量,希望这会有所帮助!
【解决方案2】:

data-&gt;data 指向什么?嗯,data-&gt;data = malloc(data-&gt;size); 这行告诉你:它指向一个未初始化的内存。

问题是,在尝试取消引用从该内存中读取的指针之前,您不会在该内存中存储任何内容。 IE。 (data_t**)data-&gt;data 很好,((data_t**)data-&gt;data)[index] 产生 未定义值data_t*,并且由于该值未定义,使用 ((data_t**)data-&gt;data)[index]-&gt;data 取消引用指针是未定义行为。

如果你想创建一个data_t 对象数组,一个间接就足够了,即。 e.使用

void create_array(data_t *data, size_t len){
  data->size = sizeof(data_t) * len;
  data->data = malloc(data->size);
  int i;
  for(i=0; i<data->size; i++){ //initialize array
    ((data_t*)(data->data))[i].data = NULL;  
    ((data_t*)(data->data))[i].size = 0;
  }
}

【讨论】:

    【解决方案3】:
    ((data_t**)(data->data))[i];
    

    在上述语句中,data-&gt;data 的计算结果为 data 结构变量 data 的成员(您应该使用不同的标识符),其类型为 void *。现在,您想将data-&gt;data 指向一个缓冲区,该缓冲区是data_t 类型的对象数组。这意味着您必须将data-&gt;data 转换为data_t *,而不是data_t **。因此,您应该将上述语句更改为

    ((data_t *)(data->data))[i];
    

    代码中的任何地方。另外,请注意free 接受void * 类型的参数,因此您不需要在将指针传递给free 之前进行类型转换。

    【讨论】:

    • @cmaster 是真的。我说的是data-&gt;data 的类型,即void *
    猜你喜欢
    • 1970-01-01
    • 2014-07-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-20
    • 2013-09-27
    • 1970-01-01
    • 2011-06-17
    相关资源
    最近更新 更多