将 *void 项添加到 *void 数组时,编译器如何知道在内存中使用多少字节?

When adding a *void item into an array of *void, how does compiler know how many bytes to use in memory?

我最近开始学习更多关于数据结构的知识,然后,在 C 中实现队列概念时,我遇到了以下问题:

typedef struct {
  int max;        /* Max. enqueed items. */
  int total;      /* Total enqueued. */
  int pos_start;  /* Pos. of first item. */
  int pos_end;    /* Pos. of last item. */
  int item_size;  /* Byte size of each item. */
  void** items;   /* Array of items. */
} queue_t;

/* 
 * Omitted code for brevity purposes. 
 */

void
queue_add(queue_t* queue, void* item)
{
  if (queue_full(queue))
  {
    fprintf(stderr, "Tried to add an item into a full queue");
    exit(1);
  }

  queue->items[queue->pos_end] = item;
  queue->total++;
  queue->pos_end = find_next_end(queue);
}

显然有效。一些注意事项:

  1. 原来的教程讲授了如何创建一个整数队列。我试图通过创建 "any" 元素的队列来挑战自己 - 这就是我尝试使用 void* 元素数组的原因。
  2. 由于我使用的是 void* 元素数组,我知道,每当我想使用此队列中的任何项目时(例如,在主要功能中使用 queue_pop) ,我需要做一个适当的铸造。通过使用转换,编译器可以准确知道该变量在内存中应占用多少字节。

但是,我的大问题是

根据我的功能,当我将新项目推入队列时,我将其保存到 queue->items[queue->pos_end]。如果编译器不知道 item 有多少字节(因为它被标记为 void*),它如何计算 queue->items[queue->pos_end] 的内存地址?

the compiler doesn't know how many bytes item has (as it's marked as a void*)

编译器确切地知道 item 由多少字节组成,因为它的类型是 指针 (到 voidint ,或指向另一个指针,或指向其他任何东西 - 无关紧要),并且所有指针都具有相同的大小(通常为 4 或 8 个字节)。

指针始终是完整类型,包括(可能是 cv 限定的)指针类型 void *void **

来自 C 标准(6.2.5 类型,第 #20 页)

— A pointer type may be derived from a function type or an object type, called the referenced type. A pointer type describes an object whose value provides a reference to an entity of the referenced type. A pointer type derived from the referenced type T is sometimes called ‘‘pointer to T’’. The construction of a pointer type from a referenced type is called ‘‘pointer type derivation’’. A pointer type is a complete object type.

这是一个演示程序。

#include <stdio.h>

int main(void) 
{
    printf( "sizeof( void * ) = %zu\n", sizeof( void * ) );

    return 0;
}

它的输出可能是

sizeof( void * ) = 8

因此,如果您有一个元素类型为 void * 的数组,那么编译器会在指针算法中使用值 8 来访问数组元素。