0

我有一个库函数,它接受一个level参数,并使用它来索引参数值数组,我将其从函数的使用者中抽象出来。请注意,参数表,甚至其结构类型仅对包含它们的 C 文件可见。

图书馆.h

#define MIN_LEVEL   0
#define MAX_LEVEL   ((sizeof(m_param_table)/sizeof(m_param_table[0]))-1)

BOOL set_param_level(int level);

图书馆.c

#include "library.h"

typedef struct {
   int param1;
   int param2;
} params_t;

// Parameters table - static (local) to this C file
static params_t m_param_table[] = {
   {0, 1},
   {2, 3},
};

BOOL set_param_level(int level) {
   int p1, p2;

   // bounds checking on MIN_LEVEL and MAX_LEVEL
   if (level < MIN_LEVEL) return FALSE;
   if (level > MAX_LEVEL) return FALSE;

   p1 = m_param_table[level].param1;
   p2 = m_param_table[level].param2;

   // do stuff with p1, p2

   return TRUE;
}

消费者.c

#include "library.h"

// Limit user input to MIN_LEVEL and MAX_LEVEL

set_param_level( user_input_value );

我希望 consumer.c 能够访问MIN_LEVELand MAX_LEVEL,以进行用户输入验证。显然,他无权访问m_param_table,因此这些宏不起作用。

最优雅和正确的方法是什么?选项是:

1) 移动typedef ... params_t到头文件,并staticm_params_table. 显然我不喜欢这样,因为它使这些东西不必要地可见。

2) 硬编码头文件中的值。当然,硬编码值很糟糕。

4

3 回答 3

5

你有第三种选择:

分别移动MIN_LEVELMAX_LEVEL创建library.c新函数get_min_level()get_max_level()在其中简单地返回和library.h实现。这些函数将在不显示库的内部数据结构的情况下可见。library.cMIN_LEVELMAX_LEVELconsumer.c

于 2013-09-01T17:17:54.253 回答
1

好吧,如果您希望您的值是常量,同时您希望隐藏表和关联的类型声明,那么一种解决方案是确实对值进行硬编码,但同时添加一个静态断言在.c文件中,这将确保硬编码的值始终是最新的。

所以,在你做的头文件中

#define MIN_LEVEL   0
#define MAX_LEVEL   1

.c你做的文件中

static params_t m_param_table[] = {
   {0, 1},
   {2, 3},
};

STATIC_ASSERT(MIN_LEVEL == 0);
STATIC_ASSERT(MAX_LEVEL == sizeof m_param_table / sizeof *m_param_table - 1);

(使用你最喜欢的STATIC_ASSERTC 实现)。

这种方法消除了硬编码值糟糕的一个最重要的原因:它们倾向于悄悄地过时。

于 2013-09-02T01:15:19.533 回答
1

编辑:添加了 const 关键字

一种选择是使用外部变量。

首先,MIN_LEVEL 和 MAX_LEVEL 不应该在 library.h 中,而应该在 library.c 中。正如您所指出的,如果没有 m_param_table 的定义,消费者将无法使用此头文件。而且您不应该仅仅为了提供对这些常量的访问而将其公开。这是你可以做的。

在 library.h 中:

extern const int min_level;
extern const int max_level;

BOOL set_param_level(int level);

在 library.c 中:

...

#define MIN_LEVEL   0
#define MAX_LEVEL   ((sizeof(m_param_table)/sizeof(m_param_table[0]))-1)

const int min_level = MIN_LEVEL;
const int max_level = MAX_LEVEL;

这使消费者可以使用常量,而不会暴露私有内部。

于 2013-09-01T17:42:15.403 回答