简体   繁体   中英

Using an array of strings to implement a symbol table in C

I am trying to use an array of structs to create a symbol table. This is what I have so far, but I am having trouble allocating memory in the create function, is what I have so far correct?

I want something like this as my final result for 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;

}
  • Use descriptive names for identifiers, not cryptic short names (like s and str_id ).
  • Avoid Systems Hungarian Notation (ie naming or prefixing identifiers after their type or what-they-are as opposed to what-they-mean).
    • In your case, I assume str_id is an abbreviation for struct_id (or string_id ) - which is a bad name because it's already immediately obvious that it's a struct (or contains a string).
    • It was popular right until the 1990s when programmers started using more powerful editors and IDEs that kept track of variable types - it just isn't needed today.
    • *
  • Always check if a heap allocation succeeded or failed by comparing calloc and malloc 's return values to NULL . This can be done with if( some_pointer ) abort() .
    • Don't use assert( some_pointer ) because assertions are only enabled in debug builds, use abort instead as it signifies abnormal program termination compared to exit .
  • Pass a size_t parameter so consumers can specify the size of the symbol table.
  • Quantities of objects held in memory should be expressed as size_t (eg array indexers). Never use int for this !
  • You need to put a semi-colon at the end of each struct definition.
  • Are you sure you want an array-of-pointers-to-structs and not just an array-of-structs ? In this case you can use inline structs and use a single allocation for the array, instead of allocating each member separately.
  • Because you're performing custom allocation, you must also define a destructor function.
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 );
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM