带有数据段内存的C中的通用静态向量数据类型

时间:2012-09-12 14:14:26

标签: c pic

是否可以在C中创建类似于数据结构的通用Vector,而不使用堆。基本上我需要一个数组数据类型,但如果它是一个更通用的版本。

typedef struct {
 /* some data types*/
}TYPE1;

typedef struct {
 /* some data types*/
}TYPE2;

typedef struct _GCACHE_T
{
        const int element_size;
        const int count;
        struct _ELEMENT {
                        UBYTE           data[element_size];
                        BOOLEAN         is_valid;
                }element[count];
}GCACHE_T;

GCACHE_T f_cache1 = {sizeof(TYPE1), 15, {0} };
GCACHE_T f_cache2 = {sizeof(TYPE2), 10, {0} };

上面的代码不会编译,但我提供了它以更清楚地说明我的要求。

如果允许堆内存使用,这将很容易实现。由于代码用于小型微堆内存,因此不允许使用。

我可以马上使用,但只是检查是否可以通用方式完成。

TYPE1 f_cache1[15];
TYPE2 f_cache2[10];

Vector的大小不会增加。我本可以使用一个联盟,但有一个记忆权衡,所以不愿意使用它。

1 个答案:

答案 0 :(得分:0)

C不支持这种参数(模板,通用)类型。您可以采用类似于BSD套接字子系统使用的方法。不同的网络地址(例如IP地址和TCP / UDP端口号)存储在不同大小的结构中(取决于地址族,例如IPv4结构比IPv6结构短)但在开始时具有类似的布局。只要需要地址,就会传递指向通用struct sockaddr类型的指针,并从套接字的地址族推断出正确的结构类型。

C支持所谓的灵活数组成员,但它不能简单地应用于您的案例,因为不仅struct _ELEMENT条目的数量不同,而且这些元素的大小也不同根据{{​​1}}的值而有所不同。这使得很难以可移植的方式计算element_size的地址,而无需参考实际类型。您可以做的是在cache.element[i].data[j]类型的开头添加一个附加字段,以帮助您确定GCACHE_T的真实大小:

struct _ELEMENT

typedef struct _GCACHE_T { int element_size; int count; size_t element_stride; struct _ELEMENT { BOOLEAN is_valid; UBYTE data[]; } element[]; } GCACHE_T; 保持具体元素类型的大小(包括任何填充)。请注意element_strideis_valid之前移动,因为C只允许结构的最后一个元素是灵活的元素。

然后您将创建特定类型,例如

data[]

如果需要声明许多不同的缓存类型,宏会派上用场。现在在typedef struct _GCACHE_TYPE1_15_T { int element_size; int count; size_t element_stride; struct { BOOLEAN is_valid; UBYTE data[sizeof(TYPE1)]; } element[15]; } GCACHE_TYPE1_15_T; GCACHE_TYPE1_15_T f_cache1 = { sizeof(TYPE1), 15, // An awful hack to obtain the size of a structure member sizeof(((GCACHE_TYPE1_15_T *)0)->element[0]) }; do_something((GCACHE_T *)&f_cache1); ,您可以计算do_something()的地址,因为您知道f_cache1.element[i].data[j]内的data字段的偏移量,并且您可以计算struct _ELEMENT的偏移量,因为单个元素的大小存储在element[i]字段中。

是的,我知道,这是一个真正的痛苦......而且我不确定需要多少指针算法才能在像PIC这样的哈佛架构设备上运行。