Hi Everyone

I just finished a program in Lua and I am really happy with it. However I committed at least two sins, I used a globals and I created a God object.

I work alone and my programs are under 2K lines of code. The program had this "design pattern" (if I can call it that)

Facts = {} -- start array
Facts["a"] = 1
Function Rules()
b = Facts["a"] * 2
end

I can start with a "starter" variable(variable "a") and then have "dependency" variables(variable "b")

"b"s value has to be updated in a function if the value of "a" changes.

Thanks for reading this far, the point is that with one global function and one global array I was able to drastically reduce the logic in my functions and I am happy with my program. Hopefully you will agree that these sins are forgiveable as I am not mixing code with others and the program is short, < 2 KLOC.

I would like to do something like this in C but arrays cannot have mixed values of strings and numbers and struct also needs to be predefined in terms of values as well.

I could simply make a whole bunch of global variables prefixed with a name such as CrazyProgrammerA = 1
CrazyProgrammerB = 2

etc, etc but surely this is extremely bad programming as i would likely end up with > 50 Globals. Is there any other way to create a C "value holder" that would only create one global and would allow mixed and random values? I guess really what I am looking for is a work around for the lack of hash tables in C.

Thanks-Patrick

Dani AI

Generated

— the pattern you used in Lua (one table holding mixed data and simple rules that read it) is a very pragmatic tradeoff for a small, solo project. is right that globals are dangerous at scale, but a single, well-encapsulated global is often a reasonable compromise. 's idea of a generic container points in the right direction: keep the mixed-type storage in one place and hide access behind a small API.

A practical C approach is to make one "context" that maps string keys to a small variant/union value, and use a proven hash-table implementation rather than many globals. Centralize allocation, getters/setters, and any validation there. Minimal illustrative layout:

typedef enum { VT_INT, VT_DOUBLE, VT_STRING, VT_PTR } ValueType;

typedef struct Value {
  char *key;
  ValueType type;
  union {
    int i;
    double d;
    char *s;
    void *p;
  } v;
  UT_hash_handle hh; /* for uthash */
} Value;

For dependencies (your "a" -> "b" case) prefer computing derived values on-demand, or use a small dirty-flag / observer system: setters mark dependents dirty or invoke update callbacks; reads recompute if dirty. That avoids stale values and the bookkeeping nightmare of many scattered globals.

Recommendations: keep exactly one context global (or pass the context pointer explicitly), expose a compact accessor API, and use a tested hash library such as uthash or embed Lua as the dynamic store if that fits the project lifecycle (Lua docs: https://www.lua.org/manual/5.4/). Also document ownership rules (who frees strings), and add locking only if concurrency is added later. For <2K LOC this gives Lua-like flexibility without proliferating globals.

Recommended Answers

All 2 Replies

there is no wise use of globals.
The only good global is an eliminated global.

Of course you can hold void *anyValue in C and cast it as appropriate. If you need to decide on the cast at run time, then you can hold an array of

struct anyValue {
  char /* or int */ dispatchTag;
  void *pointerToRealStruct;
}
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.