我有一个指向内存中malloc的块/数组的指针(void *),我知道存储在该块中的数据结构的大小 . 我希望能够遍历块以访问任何单个值 .
程序知道:
-
that void *指针将指向此malloc的内存块的开头 .
-
每个值的大小[以字节为单位],但不是实际存储的数据结构 .
-
容量[以字节为单位]:这些值的潜在数量(分配了多少内存)
这意味着我有malloc'ed:Capacity * Size_of_value字节,我想得到一个指向该块内任何值的指针,通过:
-
将void *指针转换为char *指针 .
-
将所需的Size_of_value倍数添加到char *指针:从而获得指向任何所需值的指针 .
我学到的是,将N添加到char *指针,使其向前移动N个字节 . 而且我知道指针必须以[amount]字节向前移动,我可以将[amount]添加到此char *指针 .
我找不到合适的来源,通常只能确定不允许在虚空*上使用算术 .
从我到目前为止的攻击,它似乎正常工作,只要存储的结构具有恒定的已知大小 . 结构中的灵活数组成员会破坏我当前的实现 . 这是我计划通过创建扩展来修复的缺点:列表将保存指向指针数组的指针,这些指针将提供对实际值的访问 .
可能有用也可能没用的上下文:
我正在研究列表数据结构的实现,我实现它基本上是一个动态数组(在需要时扩展和收缩),具有更多接口 .
我知道链接列表,我也计划将它们作为一个不同的练习来实现 .
我像这样定义了这个列表:
typedef struct TLIST_
{
size_t size_of_value; // size [in bytes] of each record stored in the list
size_t list_capacity; // memory has been allocated for this many values(size can't be larger than this)
size_t list_size; // number of stored records
void* pointer_to_zero; // address of the content
} tlist;
// The list has a few other values for various options and operations(e.g.: disallowing it to expand automatically, displaying the content), but those four values is all that's needed for this problem.
获取指向给定索引值的指针的函数:
void* tehlist_generic_getPointerToIndex(const tlist* list__, const int index__)
{
const int capacity = (*list__).list_capacity;
if( index__ >= 0 && index__ < capacity )
{
// Move pointer forward by a given amount of bytes, through casting the void* to a char*
// 1. Can't do pointer arithmetic on void*, but can on char*
// 2. char* is defined as 1[unit or byte],
// thus moving char* forward by N, causes it to move as if we were moving through a pointer that was of size N
void* pointer_to_index = (*list__).pointer_to_zero;
const size_t bytes_forward = (*list__).size_of_value*index__;
pointer_to_index = (char*)(pointer_to_index) + ( bytes_forward );
return pointer_to_index;
}
return 0;
}
我发现的其他信息:
GNU C编译器提供了一个C语言扩展,允许对 void*
进行算术运算,将其视为大小为1(就像它被转换为 char*
一样):
https://gcc.gnu.org/onlinedocs/gcc/Pointer-Arith.html#Pointer-Arith
这在ISO C中是不允许的,仅在GNU C中 .
2 回答
是的,转换为char *始终是合法的,取消引用该指针仅在分配的块的范围内是合法的 .
C99标准在6.3.2.3中说:
所以,只要你使用实际类型的指针(在本例中为char *)进行算术运算,它就完全有效 .