I want a generic (int/str/custom struct) set, map, ordered map, vector.
As part of relearning C I wanted to find a lightweight library (so not
GLib) that will provide generic collections.
I seem to have found such a library: https://github.com/stclib/STC
It does not appear to be a standard Debian package but I haven't found any equivalent in Debian.
Is this a reasonable choice? If not, what would you recommend?
I want a generic (int/str/custom struct) set, map, ordered map, vector.
Embracing these traits leads to more maintainable, efficient, and >understandable code. Instead of trying to force C to act like C++,
it's generally better to leverage C's strengths and use techniques
that are well-suited to the language's design and philosophy.
[email protected] (Stefan Ram) wrote or quoted:This looks like it wouldn't run much faster than in Python. So why not
Embracing these traits leads to more maintainable, efficient, and
understandable code. Instead of trying to force C to act like C++,
it's generally better to leverage C's strengths and use techniques
that are well-suited to the language's design and philosophy.
If you absolutely need a library, you (Mark) should totally check
out the Python library! It's been around forever, super reliable,
and constantly getting better. Here's a quick example program:
#include <Python.h>
int main() {
// Initialize the Python interpreter
Py_Initialize();
// Create a Python list
PyObject* pyList = PyList_New(0);
if (!pyList) {
fprintf(stderr, "Failed to create Python list\n");
Py_Finalize();
return 1;
}
// Add some integers to the list
for (int i = 0; i < 5; i++) {
PyObject* pyInt = PyLong_FromLong(i);
if (!pyInt) {
fprintf(stderr, "Failed to create Python integer\n");
Py_DECREF(pyList);
Py_Finalize();
return 1;
}
// PyList_Append increments the reference count of pyInt
if (PyList_Append(pyList, pyInt) < 0) {
fprintf(stderr, "Failed to append to list\n");
Py_DECREF(pyInt);
Py_DECREF(pyList);
Py_Finalize();
return 1;
}
// Decrease reference count of pyInt, as it's now stored in the list
Py_DECREF(pyInt);
}
// Print the list size
printf("List size: %zd\n", PyList_Size(pyList));
// Read and print the integers from the list
for (int i = 0; i < PyList_Size(pyList); i++) {
PyObject* item = PyList_GetItem(pyList, i); // Borrowed reference
if (PyLong_Check(item)) {
long value = PyLong_AsLong(item);
printf("List item %d: %ld\n", i, value);
} else {
fprintf(stderr, "List item %d is not an integer\n", i);
}
}
// Clean up
Py_DECREF(pyList);
Py_Finalize();
return 0;
}
, output:
List size: 5
List item 0: 0
List item 1: 1
List item 2: 2
List item 3: 3
List item 4: 4
.
This looks like it wouldn't run much faster than in Python. So why not
just use Python? It would be a lot simpler!
I've never hear of it, but from a very quick look I'd say: no.
They seem to be trying to write C++ code in C. If you want C++, use C++.
I want a generic (int/str/custom struct) set, map, ordered map, vector.
I think this is better (I've never used it, but Jacob does know what
he's doing): https://github.com/jacob-navia/ccl
Really though, roll your own. It'll be a good exercise for relearning C.
C is a stripped-down language designed to get close to the hardware
with minimal overhead. It skips many of the high-level features in
C++, like templates, classes, and operator overloading. Trying to make
C act like C++ by building a generic container library can lead to:
Complexity: Creating generic containers in C often means dealing with
gnarly macros, void pointers, and type casting,
which can make the code a pain to read and maintain.
Inefficiency: Generic containers in C might not be as slick as those
in C++ due to the lack of compile-time type checking and
optimizations. And,
error-prone code: Without the type safety provided by C++ templates,
generic containers in C are more likely to cause runtime errors.
Idiomatic C programming rolls with the language's strengths and works
within its constraints. This often involves:
Explicit typing: C programmers usually define data structures and
functions explicitly for each type they need, rather than leaning on
generic solutions.
Manual memory management: C programmers are used to managing memory by
hand, which can be more predictable and efficient than relying on a
generic container library. And,
simplicity and clarity: C code is often straightforward and simple,
focusing on clear and direct solutions rather than abstract and
generalized ones.
The old pros of C came up with several techniques to handle the lack
of generic containers:
Structs and pointers: Using structs and pointers to create custom data
structures tailored to specific needs.
Function pointers: Employing function pointers to pull off a form of
polymorphism. And,
Macros: Utilizing preprocessor macros to create reusable code
snippets, though this can lead to less readable and maintainable code
if overdone.
Some problems encountered when using generic container libraries in C
might be:
portability: Generic container libraries in C can be less portable
across different compilers and platforms.
Debugging: Debugging generic code in C can be more of a hassle due to
the lack of type information and the use of void pointers. And,
performance: Hand-crafted, type-specific data structures and
algorithms can often be more performant than generic implementations.
While it's technically possible to whip up a generic container library
in C, doing so often goes against the grain of idiomatic C
programming.
C shines in simplicity, explicitness, and low-level control.
Embracing these traits leads to more maintainable, efficient, and
understandable code. Instead of trying to force C to act like C++,
it's generally better to leverage C's strengths and use techniques
that are well-suited to the language's design and philosophy.
I've started reading Jacob Navia's CCL document.
This seems to provide all that I'd need (and more besides).
However, it appears that this was intended to be added to C's standard library — 12 years ago! The last update was 4 years ago. So it doesn't
look to be maintained and presumably was rejected as an addition to the standard library?
Macros can get into the realm
of unreadability, but there's an unfortunate feedback loop here: people
are told to not use macros because they're unreadable, which means that people don't get as much experience with macros, which means that they
find it hard to read macros ...
On Sun, 4 Aug 2024 14:05:00 -0000 (UTC), Blue-Maned_Hawk wrote:
Macros can get into the realm of unreadability, but there's an
unfortunate feedback loop here: people are told to not use macros
because they're unreadable, which means that people don't get as much
experience with macros, which means that they find it hard to read
macros ...
Macros done by manipulating strings in a preprocessor are the wrong way
to do them.
The right way to do macros is at the AST level, like Lisp does them.
On Mon, 5 Aug 2024 16:35:52 -0000 (UTC), Blue-Maned_Hawk wrote:
Lawrence D'Oliveiro wrote:
Macros done by manipulating strings in a preprocessor are the wrong
way to do them.
The right way to do macros is at the AST level, like Lisp does them.
Standard C preprocessors are already token-based instead of text-based
like prestandard ones were.
Not what I said.
Lawrence D'Oliveiro wrote:
Macros done by manipulating strings in a preprocessor are the wrong way
to do them.
The right way to do macros is at the AST level, like Lisp does them.
Standard C preprocessors are already token-based instead of text-based
like prestandard ones were.
| Sysop: | Keyop |
|---|---|
| Location: | Huddersfield, West Yorkshire, UK |
| Users: | 715 |
| Nodes: | 16 (2 / 14) |
| Uptime: | 21:44:20 |
| Calls: | 12,104 |
| Calls today: | 4 |
| Files: | 15,004 |
| Messages: | 6,518,114 |