c-铸造void指针并使用格式说明符打印



好的,这是针对一个学校项目的,但我的问题与特定实现无关,我也没有寻求任何关于项目本身的帮助。我之所以发出这个警告,只是因为我想为我正在做的事情提供背景,但这是一个关于在项目背景下铸造无效指针的一般问题。。。我正在编写的这个函数甚至不适用于项目,它只是我作为一种测试机制编写的,以查看我生成的数据结构是否有效。。。这让我遇到了一个涉及printf()、格式说明符和强制转换的问题。。。。我基本上必须实现一个链表(称为"队列",但实际上根本不是一个队列),我写了一个函数来测试它

基本上有一个称为"Chunk"的结构,它包含一些变量(first是较大数组中的索引,该数组是给定"Chunk"的第一个元素,arr基本上是larger_array[c->first],但它实际上是一个void指针,如下所示:void*arrc是指向Chunk的指针),这些变量指示较大阵列中的位置。因此,基本上,如果你有一个像a={5,7,3,4,6,9,1,2}这样的数组,并且你得到了一个2的块大小,你有4个块,每个块都有一个"arr"void指针变量,分别指向5,然后是3,然后是6,然后是1。

无论如何,我写了一个"print_queue"函数(实际上是Chunks的链表),耶!它根据需要打印所有信息,这里是我将分享的核心部分:

 while (index < num_chunks) {
    first = c->first;
    printf("Chunk %d: first is %d and a[%d] is ", index, first, first);
    if (elem_size == LONG_SIZE) /* LONG_SIZE defined above as 8 */
      printf("%ldn", c->arr);
    else if (elem_size == INT_SIZE) /* INT_SIZE defined above as 4 */
      printf("%dn", c->arr);
    else if (elem_size == CHAR_SIZE) /* CHAR_SIZE defined above as 1 */
      printf("%cn", c->arr);
    index++;
    if (c->next != NULL)
      c = c->next;
 }

我基本上想写一个函数,当我实现项目的实际功能(多线程合并排序)时,它可以打印三种类型(long、int和chars)中任何一种的链表,用于测试目的。所以上面的代码确实有效!这是此数组输入的输出:

 char original[] = {'z', 'y', 'x', 'w', 'v', 'u', 't', 's'};

输出:

 Chunk 0: first is 0 and a[0] is z
 Chunk 1: first is 2 and a[2] is x
 Chunk 2: first is 4 and a[4] is v 
 Chunk 3: first is 6 and a[6] is t

所以它有效!耶!然而,我收到了以下编译器警告:

mergesort.c: In function 'print_chunk_queue':
mergesort.c:85:7: warning: format '%ld' expects argument of type 'long int', but     argument 2 has type 'void *' [-Wformat]
mergesort.c:87:7: warning: format '%d' expects argument of type 'int', but argument 2 has type 'void *' [-Wformat]
mergesort.c:89:7: warning: format '%c' expects argument of type 'int', but argument 2 has type 'void *' [-Wformat]

所以我所做的是将所有的c->arr转换为(type*)c->arr,但这给了我更多关于"哦,我们想要一个int,但你有一个int指针"的警告,所以我当时所做的就是:

 * ((type *) c->arr)

基本上是取消引用我的casted void指针(它从来都不是null!它总是指向有效的数字,至少在我提供的输入中是这样!),然后这给了我一个分段错误!。所以我很沮丧,因为我从处理带有大量"警告"的输出变成了无用的分段错误。

编辑:

根据要求定义数据结构:

typedef struct chunk {
  void *arr;
  struct chunk *next;
  int first;
} Chunk;

这就是我如何设置单个块的状态并创建块的链接列表:

  while (index < number_of_chunks) {
    if (index == 0) {
      if ((current = malloc(sizeof(Chunk))) == NULL)
        err(EX_OSERR, "memory allocation has failedn");
      head = current;
    }
    current->first = (chunk_size * index);
    current->arr = ((char *) array)[current->first];
    current->size = chunk_size;
    if (index != (number_of_chunks - 1)) {
      if ((current->next = malloc(sizeof(Chunk))) == NULL)
        err(EX_OSERR, "memory allocation has failedn");
      current = current->next;
   }
  else {
    tail = current;
  }
  index += 1;
}
current->arr = ((char *) array)[current->first];

这里应该有一个&。您希望将字节的地址分配给arr,而不是其

current->arr = &((char *) array)[current->first];

如果这样做,那么arr将包含一个应该包含的地址,这将允许强制转换&工作失职。

printf("%ldn", *(long *) c->arr);
printf("%dn",  *(int  *) c->arr);
printf("%cn",  *(char *) c->arr);

最新更新