我试图在C中自己实现常见的数据结构,以获得自己的学习效益。我目前的努力是一个向量,我希望它能够保存一个任意类型(或者至少是类型大小,但是在C中真的不重要吗?)。我的结构如下:
struct vector
{
void *item;
size_t element_size;
size_t num_elements;
}
但是,我不明白的是,如果类型应该是任意的,我可以如何引用* item数组中的特定元素。我知道element_size,但这对索引引用没有帮助(例如item [5]),因为void不是一个类型。我认为最简单的方法是将元素称为字节偏移量。因此,如果我持有大小为12的结构向量,则项目[5]将在项目*的12 * 5 = 60字节处。但是,我不明白如何检索该数据。我知道我需要来自item + 60的12个字节,但是如何让编译器理解呢?我是否进入预处理器领域?
答案 0 :(得分:2)
sizeof
是字符中的度量,因此您可以执行此操作:
void *start_of_sixth_element = ((char*)item) + (5 * element_size);
知道每个元素类型的人可以将start_of_sixth_element
强制转换为正确的类型以使用它。
void*
在某种程度上是一个糟糕的选择,因为你不能用标准C中的void*
指针进行指针运算(有一个允许它的GNU扩展,但对于你使用的可移植代码{至少对于算术来说{1}}或char*
。
在应用偏移量5之前知道正确类型的代码,可以这样做:
unsigned char*
void不是类型
这是一种类型,它不是“完整类型”。 “不完整类型”几乎意味着编译器不知道correct_type *sixth_element = ((correct_type *)item) + 5;
真正指向的是什么。
答案 1 :(得分:0)
void *
是任何对象指针类型的通用指针类型。你必须知道它指向的是什么类型才能正确地转换void *
并取消引用指针。
以下是使用不同指针类型的void *
对象的示例。
void *p;
int a = 42, b;
double f = 3.14159, g;
p = &a;
b = *(int *) a;
p = &f;
g = *(double *) f;
答案 2 :(得分:0)
因此,如果我持有大小为12的结构向量,则项目[5]将在项目*的12 * 5 = 60字节处。但是,我不明白如何检索该数据。我知道我需要来自item + 60的12个字节,但是如何让编译器理解呢?
假设您的给定类型为foo
。如您所知,您需要到达item + (5 * 12)
处的地址,然后在将其转换为foo*
后取消引用该空指针。
foo my_stuff = *(foo *)(item + 5 * 12);
如果您可以在编译时确定数据类型,也可以使用sizeof()
:
foo my_stuff = *(foo *)(item + 5 * sizeof(foo));