Princeton University
COS 217: Introduction to Programming Systems

The SymTable ADT and the Circuit Simulator

The Problem

Your circuit simulator program should be a client of your SymTable ADT.  Specifically, you will find it convenient to define your Circuit module so it creates and uses two SymTable objects: one that relates each input name (of type string) to a unique index (of type int), and another that relates each flip flop name (of type string) to a unique index (of type int).

Thus each SymTable object should contains bindings whose values are integers. However, a SymTable object stores its values as void pointers. So the problem is this: how can you store integers as values within a SymTable object when it expects them to be void pointers? 

There are two solutions...

Solution 1

On the arizona cluster, it happens that the amount memory required to store an integer (4 bytes) is the same as the amount of memory required to store a void pointer, or a pointer of any type. Thus you can use the cast operator to "trick" the compiler into generating code that will store integers as void pointers, using statements similar to these:

SymTable_put(oFlipFlopSymTable, "A", (void*)0);
...
SymTable_put(oFlipFlopSymTable, "B", (void*)1);
...
iIndex = (int)SymTable_get(oFlipFlopSymTable, "A");
...
iIndex = (int)SymTable_get(oFlipFlopSymTable, "B");

Note that solution1 works on only those systems for which sizeof(int) <= sizeof(void*).

Solution 2

The second solution is the more portable one: you can place each integer in memory, and then store memory addresses in the SymTable object. Since you do not know a priori how many integers you will need, you must allocate that memory dynamically.  The code will be similar to this:

pi = (int*)malloc(sizeof(*pi));
*pi = 0;
SymTable_put(oFlipFlopSymTable, "A", pi);
...
pi = (int*)malloc(sizeof(*pi));
*pi = 1;
SymTable_put(oFlipFlopSymTable, "B", pi);
...
iIndex = *(int*)SymTable_get(oFlipFlopSymTable, "A");
...
iIndex = *(int*)SymTable_get(oFlipFlopSymTable, "B");

Of course you must free the memory in which each integer resides when that memory is no longer needed.  You can do that by mapping a "freeInt" function (which you must define) across all values in the SymTable object:

SymTable_map(oSymTable, freeInt, NULL);

Note that solution 2 works on any system.

Which Solution is Better?

Solution 1 is more efficient but less portable. Solution 2 is less efficient but completely portable. Usually portability is more important than efficiency, so we recommend solution 2.