使用字符串数组在 C 中实现符号 table
Using an array of strings to implement a symbol table in C
我正在尝试使用结构数组来创建符号 table。这是我目前所拥有的,但我在创建函数中分配内存时遇到问题,我目前所拥有的是正确的吗?
我想要这样的结果作为 arr 的最终结果
{ {"sym1"; 1}, {"sym2"; 2}, {"sym3"; 3} }
struct str_id {
char* s;
int id;
}
struct symbol_table {
int count;
struct str_id** arr;
}
struct symbol_table *symbol_table_create(void) {
struct symbol_table *stt = malloc(sizeof(struct symbol_table));
stt->count = 1;
stt->arr = malloc(sizeof(struct str_id*) * stt->count);
return stt;
}
- 对标识符使用描述性名称,而不是神秘的短名称(如
s
和 str_id
)。
- Avoid Systems Hungarian Notation(即在它们的类型或它们是什么而不是它们的意思之后命名或前缀标识符)。
- 在你的情况下,我假设
str_id
是 struct_id
(或 string_id
)的缩写 - 这是一个糟糕的名字,因为它已经很明显是 struct
(或包含一个字符串)。
- 它一直流行到 1990 年代,当时程序员开始使用更强大的编辑器和 IDE 来跟踪变量类型——只是今天不需要它了。
*
- 始终通过比较
calloc
和 malloc
的 return 值与 NULL
来检查堆分配是成功还是失败。这可以用 if( some_pointer ) abort()
来完成。
- 不要使用
assert( some_pointer )
,因为断言仅在调试版本中启用,请使用 abort
,因为与 exit
. 相比,它表示程序异常终止
- 传递一个
size_t
参数,以便消费者可以指定符号的大小 table。
- 内存中保存的对象数量应表示为
size_t
(例如数组索引器)。 Never use int
for this!
- 您需要在每个
struct
定义的末尾放置一个分号。
- 您确定要
array-of-pointers-to-structs
而不仅仅是 array-of-structs
吗?在这种情况下,您可以使用内联结构并为数组使用单个分配,而不是单独分配每个成员。
- 因为您正在执行自定义分配,所以您还必须定义一个析构函数。
struct symbol_table_entry {
char* symbolText;
int id;
};
struct symbol_table {
size_t count;
struct symbol_table_entry** entries;
};
struct symbol_table* create_symbol_table( size_t count ) {
struct symbol_table* stt = malloc( sizeof(struct symbol_table) );
if( !stt )
{
abort();
}
stt->count = count;
stt->entries = calloc( count, sizeof(struct symbol_table_entry) );
if( !stt->entries ) {
free( stt );
abort();
}
// Note that calloc will zero-initialize all entries of the array (which prevents debuggers showing garbage string contents) so we don't need to do it ourselves.
return stt;
}
void destroy_symbol_table( struct symbol_table* stt, bool free_strings ) {
if( stt->entries ) {
if( free_strings ) {
for( size_t i = 0; i < stt->count; i++ ) {
free( stt->entries[i]->symbolText );
}
}
free( stt->entries );
}
free( stt );
}
我正在尝试使用结构数组来创建符号 table。这是我目前所拥有的,但我在创建函数中分配内存时遇到问题,我目前所拥有的是正确的吗?
我想要这样的结果作为 arr 的最终结果 { {"sym1"; 1}, {"sym2"; 2}, {"sym3"; 3} }
struct str_id {
char* s;
int id;
}
struct symbol_table {
int count;
struct str_id** arr;
}
struct symbol_table *symbol_table_create(void) {
struct symbol_table *stt = malloc(sizeof(struct symbol_table));
stt->count = 1;
stt->arr = malloc(sizeof(struct str_id*) * stt->count);
return stt;
}
- 对标识符使用描述性名称,而不是神秘的短名称(如
s
和str_id
)。 - Avoid Systems Hungarian Notation(即在它们的类型或它们是什么而不是它们的意思之后命名或前缀标识符)。
- 在你的情况下,我假设
str_id
是struct_id
(或string_id
)的缩写 - 这是一个糟糕的名字,因为它已经很明显是struct
(或包含一个字符串)。 - 它一直流行到 1990 年代,当时程序员开始使用更强大的编辑器和 IDE 来跟踪变量类型——只是今天不需要它了。 *
- 在你的情况下,我假设
- 始终通过比较
calloc
和malloc
的 return 值与NULL
来检查堆分配是成功还是失败。这可以用if( some_pointer ) abort()
来完成。- 不要使用
assert( some_pointer )
,因为断言仅在调试版本中启用,请使用abort
,因为与exit
. 相比,它表示程序异常终止
- 不要使用
- 传递一个
size_t
参数,以便消费者可以指定符号的大小 table。 - 内存中保存的对象数量应表示为
size_t
(例如数组索引器)。 Never useint
for this! - 您需要在每个
struct
定义的末尾放置一个分号。 - 您确定要
array-of-pointers-to-structs
而不仅仅是array-of-structs
吗?在这种情况下,您可以使用内联结构并为数组使用单个分配,而不是单独分配每个成员。 - 因为您正在执行自定义分配,所以您还必须定义一个析构函数。
struct symbol_table_entry {
char* symbolText;
int id;
};
struct symbol_table {
size_t count;
struct symbol_table_entry** entries;
};
struct symbol_table* create_symbol_table( size_t count ) {
struct symbol_table* stt = malloc( sizeof(struct symbol_table) );
if( !stt )
{
abort();
}
stt->count = count;
stt->entries = calloc( count, sizeof(struct symbol_table_entry) );
if( !stt->entries ) {
free( stt );
abort();
}
// Note that calloc will zero-initialize all entries of the array (which prevents debuggers showing garbage string contents) so we don't need to do it ourselves.
return stt;
}
void destroy_symbol_table( struct symbol_table* stt, bool free_strings ) {
if( stt->entries ) {
if( free_strings ) {
for( size_t i = 0; i < stt->count; i++ ) {
free( stt->entries[i]->symbolText );
}
}
free( stt->entries );
}
free( stt );
}