2

我必须设计一个抽象数据类型,但我不允许使用动态分配。好像有点棘手……

我目前拥有的:

在 adt.c 中:

struct adt
{
  bool b;
};

const size_t adtSize = sizeof( struct adt );

// Initialisation of the adt
void Adt_New( struct adt* anAdt, bool b )
{
  // No calloc allowed...
  anAdt->b = b;
}

在 adt.h 中,丑陋的部分来了:

struct adt; // adt structure

extern const size_t adtSize;

// Bear with me...    
#define ADT_DATA( NAME ) uint8_t NAME ## _storage[ adtSize ]; \
    memset( &NAME ## _storage , 0 , adtSize ); \
    struct adt* NAME = (adt*) & NAME ## _storage;

现在我可以像这样使用它:

void TestAdt()
{
  ADT_DATA( a );

  Adt_New( a, true );
}

在专业方面,我有一个不透明的数据类型,我不必使用动态分配。

不利的一面,这只是丑陋的。当我尝试不在函数内(例如全局)调用 ADT_DATA( ... ) 时,我收到一条错误消息。

有可能改善这一点吗?目前,我唯一的选择是公开数据类型......

TIA 为您的想法!

4

1 回答 1

3

您的方法根本行不通,因为一旦您开始将该uint8_t缓冲区用于不相关的目的,您就违反了严格的别名。事实上,这就是你在这里所做的:struct adt* NAME = (adt*) & NAME ## _storage;. 那是未定义的行为。

通常,通过在 ADT 中创建自己的内存池来解决无法访问 malloc(如在您的普通嵌入式系统中)的问题。内存池是一个不透明结构类型的 X 对象数组。这是一个带有不透明指针的示例:

头文件:

typedef struct adt adt;

C 文件:

struct adt
{
  // stuff
};


static adt mempool [X];
static size_t mempool_size;    

adt* adt_alloc (/* stuff */)
{
  adt* new_obj;

  new_obj = &mempool[mempool_size];

  mempool_size++;
  if(mempool_size == MAX)
  { /* handle error */ }

  new_obj->this = 123;
  new_obj->that = 456;
  ...

  return new_obj;
}

这种方法对更复杂的 ADT 最有意义。对于更简单的结构,所需的开销可能不值得,在这种情况下,您应该考虑将整个结构公开。

也存在其他方法,我强烈建议阅读所有不透明数据类型的静态分配。很多不错的提示和技巧。

于 2016-09-30T11:35:53.783 回答