将 *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);
}
显然有效。一些注意事项:
- 原来的教程讲授了如何创建一个整数队列。我试图通过创建 "any" 元素的队列来挑战自己 - 这就是我尝试使用
void*
元素数组的原因。
- 由于我使用的是
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
由多少字节组成,因为它的类型是 指针 (到 void
或 int
,或指向另一个指针,或指向其他任何东西 - 无关紧要),并且所有指针都具有相同的大小(通常为 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 来访问数组元素。
我最近开始学习更多关于数据结构的知识,然后,在 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);
}
显然有效。一些注意事项:
- 原来的教程讲授了如何创建一个整数队列。我试图通过创建 "any" 元素的队列来挑战自己 - 这就是我尝试使用
void*
元素数组的原因。 - 由于我使用的是
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
由多少字节组成,因为它的类型是 指针 (到 void
或 int
,或指向另一个指针,或指向其他任何东西 - 无关紧要),并且所有指针都具有相同的大小(通常为 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 来访问数组元素。