创建 n 大小字节的数据类型 [英] Create data type of n size bytes

查看:67
本文介绍了创建 n 大小字节的数据类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在为 C 中的队列制作一个类似弹性缓冲区的单文件头库.
我将数组作为 void* 和单个元素的大小传递给函数之一:

I am making a stretchy-buffer-like single-file header library for queues in C.
I am passing the array as a void* and the size of a single element to one of the functions:

void func(void* arr, size_t itemsize);

func()里面我需要用arr做一些指针运算.
我不能用 void* 做算术运算,所以我想我可以创建一个大小为 itemsize 的数据类型,我可以将 arr 转换成,从而解决我的问题.

Inside func() I need to do some pointer arithmetic with arr.
I can't do arithmetic with void*, so I thought I could create a data type of size itemsize that I could cast arr into, and thus solve my problem.

我看到了公认的这个问题,但是 char*[] 上的指针算术会按我想要的方式工作吗?如,(char*[5])(arr) + 3arr 后的 15 个字节,&((char*[4])(arr))[6] 指向 arr 之后的 24 个字节.

I saw the accepted this question, but would pointer arithmetic on char*[] work the way I want? As in, (char*[5])(arr) + 3 is 15 bytes past arr, and &((char*[4])(arr))[6] points to 24 bytes past arr.

我需要创建类型 inside func.

推荐答案

我们可以看看 GLib 做他们的数组.如果这是用于生产代码,只需使用 GLib.

We can look at how GLib does their arrays. And if this is for production code, just use GLib.

首先,不要传递大小和指针.创建一个包含大小和数组以及其他任何内容的结构.这允许您传递完整的数组.更简单,更不容易出错.以下是 GLib 如何做到这一点.重要的部分是 data(guint8 是 uint8 的 GLib 版本 或 1 个字节)和 elt_size(元素大小).剩下的是肉汁.

First, don't pass around the size and pointer. Make a struct which contains the size and the array and anything else. This allows you to pass around the complete array. Far simpler and less error prone. Here's how how GLib does it. The important bits are data (guint8 is the GLib version of uint8 or 1 byte) and elt_size (element size). The rest is gravy.

struct _GRealArray
{
  guint8 *data;
  guint   len;
  guint   alloc;
  guint   elt_size;
  guint   zero_terminated : 1;
  guint   clear : 1;
  gatomicrefcount ref_count;
  GDestroyNotify clear_func;
};

我们可以看看g_array_insert_vals 查看如何在索引处插入值.插入的内容在这里.

We can look at g_array_insert_vals to see how to insert values at an index. The meat of the insertion is here.

memcpy (g_array_elt_pos (array, index_), data, g_array_elt_len (array, len));

特殊的酱汁都在g_array_elt_pos(元素位置)和 g_array_elt_len(元素大小)宏.g_array_elt_pos(array, i) 复制 array[i].

The special sauce is all in the g_array_elt_pos (element position) and g_array_elt_len (element size) macros. g_array_elt_pos(array, i) replicates array[i].

#define g_array_elt_len(array,i) ((array)->elt_size * (i))
#define g_array_elt_pos(array,i) ((array)->data + g_array_elt_len((array),(i)))

数据存储为 8 位整数.g_array_elt_len 通过将元素大小乘以索引来计算距数组开头的偏移量.然后 g_array_elt_pos 将其添加到数组的开头.

The data is stored as 8 bit integers. g_array_elt_len calculates the offset from the start of the array by multiplying the element size by the index. Then g_array_elt_pos adds that to the start of the array.

那个 memcpy 是有效的...

That memcpy is effectively...

memcpy(array[index_], data, (array->elt_size * len));

array->elt_size大小的len单元从data复制到array[i].

Copy len units of array->elt_size size from data to array[i].

查找元素需要类型转换.GLib 使用宏为您处理此问题.它返回一个指向元素的指针.

Looking up an element requires a type cast. GLib takes care of this for you with a macro. It returns a pointer to the element.

#define g_array_index(a,t,i)      (((t*) (void *) (a)->data) [(i)])

例如.

// Similar to double num = array[5]
// Expands to ((double*) (void *) array->data)[5]
double num = g_array_index(array, double, 5);

这篇关于创建 n 大小字节的数据类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆