如何取消虚空*作为空洞的数组*

时间:2014-03-22 10:33:59

标签: c arrays struct void-pointers

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

结构如下:

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]

并且我遇到了访问冲突。

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

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

#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;
}

3 个答案:

答案 0 :(得分:2)

当data-&gt; data是指针数组时,使用

((data_t**)(data->data))[i],尝试

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

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

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

答案 1 :(得分:1)

data->data指向什么?那么,data->data = malloc(data->size);行告诉你:它指向未初始化的记忆。

问题是,在尝试取消引用从此内存中读取的指针之前,不要在该内存中存储任何内容。 I. e。 (data_t**)data->data没问题,((data_t**)data->data)[index]会产生{{1>} 未定义值,并且由于该值未定义,因此使用data_t*取消引用指针是未定义的行为

如果你想创建一个((data_t**)data->data)[index]->data个对象的数组,一个间接就足够了,i。即使用

data_t

答案 2 :(得分:1)

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

在上面的语句中,data->data计算结构变量data的{​​{1}}成员(您应该使用不同的标识符),类型为data。现在,您希望将void *指向缓冲区,该缓冲区是data->data类型的对象数组。这意味着您必须将data_t投射到data->data,而不是data_t *。因此,您应该将上述语句更改为

data_t **

代码中的任何地方。另请注意,((data_t *)(data->data))[i]; 采用free类型的参数,因此您无需在将指针传递给void *之前投射指针。