Data representation in C : Linked structs vs Big structs - c

While looking at someone's code i was struck by a way of representing data which, in a C context, seemed strange to me :
This person needed to represent different kind of geometries for a raytracer,
each geometries while being different had similarities in their structures.
So this person decided to represent the geometries through more or less abstract structs linked together through pointers.
s_entities -> s_scene_object -> s_sphere
s_entities -> s_scene_object -> s_plane
s_entities -> s_pointlight
i was wondering why one would decompose its data in C through abstraction layers instead of having an all-encompassing struct for each kind of data.
One explanation would be to reduce overhead if you have functions that operate on a certain layer of abstration of your data. right ?
it seems to me like remnants of OOP habits.

You say "remnants of OOP habits" as if that's something that's obviously not OK in C. I'd say you're wrong, there are rather large collections of very heavily object-oriented code in C. It works.
Object-orientedness is a way to arrange and model things, it's not tied to programming languages. C is low-level enough that you can do all sorts of programming paradigms in it; you'll often have to implement much of the paradigm yourself since there is little support from the language, but OO is pretty straight-forward.
It's not very clear from your example, but a more typical way to model things like that in C is by embeddeding the more basic data structure (superclass) inside the more specialized, utilizing the fact that the first member in a C struct is at offset 0 from the struct itself:
typedef struct {
float x, y, z;
} Shape;
typedef struct {
Shape shape;
float radius;
} Sphere;

Related

Use of function pointers in C on data structure development

I'm having an Algorithms course next semester and so I dived into C with the purpose of making a few data structures ahead of time to be prepared.
As I learned about function pointers, I found I could store them in structs and create an object-oriented-like use for my data structure. Here's an example:
#include <stdio.h>
void insert(char * object)
{
printf("Adding %s to the data structure\n", object);
}
typedef struct data_structure {
char * obj;
void (*insert)(char * object);
} data_structure;
int main()
{
data_structure d;
d.insert = insert;
d.insert("bacon");
return 0;
}
But is this kind of procedure actually useful in the scope of data structure and algorithm studying in C? Or is it just taking up memory on the data structure?
I've found other posts talking about function pointers, but none that explores this kind of approach. I think this could be useful to a bunch of curious students out there :)
In the past I have certainly seen objects constructed this way as sets of function pointers effectively representing a vtable. Usually, for a vtable you add one extra level of indirection such that all data objects with similar traits point to the same function pointer object. This reduces the cost per data object if there is more than 1 function, but at a slight execution cost.
It can also be used as a lightweight way to organise and structure function+voiddata callback objects, by insisting that the first member of the data is the callback function. Of course, you can't define inherited classes using c, but you can have nested structures which can be bullied to the same purpose.
After reading all the answers, here's the insight this post gathered regarding the use of function pointers as C structure attributes.
Advantages:
Good ol' practise on a somewhat advanced subject if you're a student
Provides encapsulation and object oriented code in C
Gives you better understanding of the object orientated programming paradigm if you're not already well familiarized with it
Can be used to implement VTables
Disadvantages:
On a functional level, you still have to pass the data structure to the function, as it doesn't have access to said data structure
Slight performance overhead
In conclusion, the use of function pointers as in the original question would really only have practical uses if one wishes to explore OOP whilst getting into more advanced aspects of C, or to construct VTables.
Thank you to all the people who replied.

Is there a more efficient way to store an n-ary tree in a file in C?

Say I'm writing an adventure game. The map is built of tiles of different types. I have tiles that form paths, and tiles that form doors, and so on.
I will use a struct to describe the type and content of a tile, and to which other tiles it connects.
Then I'll make a quadruple-linked list to connect them all together.
But a struct that will describe a room will have far more elements than one that will describe a door, so many elements in a door struct will be redundant. I could make a smaller door struct, but structs can only point to structs of the same type*, so I couldn't connect a room struct to a door struct. The redundancy may be negligible but I wondered if there's another way.
Another option is using an array of structs, but then I'd have lots of 'padding' structs wasting even more space. However an array would make reading and re-building a map from file much easier.
Is there any way around the limitation that a struct can only point to a struct of the same type? Or is there another common solution to this problem that I haven't mentioned?
One idea I had was that each tile could have pointers for every other type of tile. Some would be redundant, but it would be a lesser redundancy that the option above.
*By this I mean that typically in a linked list, structs contain pointers to struct of the same type that they're in.
You really don't have to have a uniform struct describing everything. Instead, you could do the following (this is somewhat like writing your own C++ virtual tables in C, and is very widely used).
Your basic tile struct can look like this:
struct tile
{
// common tile stuff
...
enum tile_type type;
void *type_info;
};
So in this struct you store stuff that's common to every tile type. Then you make other structs for other types: one for a room, one for a path, etc. Within an object of tile, you make the enum describe the actual type, and store a pointer to the concrete type within the void *.
There are many links describing variations of this technique. Here's one.
Instead of storing elements in a tile, store only a pointer to the linked list of elements.

how to program high level concepts (i.e. Object class, and Generics) in C

Here lately I've been tinkering around with my own languages as well as reading various writings on the subject.
Does anyone have any good advice on how, in C (or Assembler), do you program the concept of the Object Class and/or the concept of Generics into a language. (referring to the Java implementations of Object and Generics)
For instance, in Java all all classes extend Object. So how do you represent this at the C level? is it something like:
#include <stdio.h>
typedef struct {
int stuff;
} Object;
typedef struct {
int stuff;
Object object;
} ChildClass;
int main() {
ChildClass childClass;
childClass.stuff = 100;
childClass.object.stuff = 200;
printf("%d\n", childClass.stuff);
printf("%d\n", childClass.object.stuff);
}
And I'm not really even sure how to get started with implementing something like Generics.
I also appreciate any valuable links regarding program langauge design.
Thanks,
Take a look at Structure and Interpretation of Computer Programs by Abelson and Sussman. While it doesn't show how to do it in C, it does demonstrate how to create types at run time and how to build an object system on top of a language that doesn't provide native support. Once you understand the basic ideas, you should be able to use structs and function pointers to create an implementation. Of course, looking at the source code for a C++ preprocessor will also be instructive. At one time, C++ was just a preprocessor for a C compiler.
I found this book a little while ago that has been an interesting read: Object-Oriented Programming With ANSI-C (PDF).
In C I've created class-like structures and methods by using structs (to store the class's state) and functions that take pointers to them (methods of the class). Implementing things like inheritance is possible, but would get messy fast. I'm not a Java guy though, and I'm not sure how much of Java you should press onto C, they are very different languages.
Here's probably the crudest form of a object implementation possible; I wrote it to run multiple PID controls at the same time.
//! PID control system state variables
typedef struct {
const PID_K * K; //!< PID control parameters
int32_t e; //!< Previous error (for derivative term)
int32_t i; //!< Integrator
} PID_SYS;
void PID_Init(PID_SYS * sys, const PID_K * K)
{
sys->i = 0;
sys->e = 0;
sys->K = K;
}
int16_t PID_Step(PID_SYS * sys, int32_t e)
{
// ...PID math using "sys->" for any persistent state variables...
}
If your goal is to write a new language that incorporates high level concepts, you might want to look at the CPython sources. CPython is an object oriented programming language whose interpreter is written in C. Open source C implementations of compilers/interpreters for C++, D, Javascript, Go, Objective C, and many, many others exist as well.
It's more complicated, but you're on the right path. Actual implementations use roughly the same code as yours to achieve inheritance (but they actually use containment to do it, which is quite ironic), along with a per-instance table of function pointers (virtual functions) and some (okay, many) helper macros.
See gobject.
It's definitely not C, but I'd recommend taking a look at Lua.
At its core, Lua only has a few basic types: number, string, boolean, function, and table (there's a couple more outside of the scope of this topic, though. A table is essentially just a hashtable that accepts keys of any type and can contain values of any type as well.
You can implement OOP in Lua by way of metatables. In Lua, a table is allowed to have up to one metatable, which is accessed under special circumstances, such as when a table is added or multiplied to another table or when you try to access a key that is not present in the table.
Using metatables, you can quickly and easily achieve something quite like inheritance by chaining together multiple metatables. When you try to access a missing key in a table, Lua looks up a key named __index in that table's metatable. So if you try to access a key named foo on a table that doesn't have such a key, Lua will check for foo in the first metatable. If it isn't present there and that metatable has a metatable of its own with __index defined, it will check for foo in the next one, and so on.
Once you realize how simple it is to do this in Lua, translating it to C is very achievable. Your OOP will be completely at run-time, of course, but it will be very OOP-like indeed.

C program variable that holds cartesian coordinates?

I have never programmed in C and have not programmed in C++ for a little while and either way, I am still learning.
I am writing a program in C and am converting a MATLAB program to this C program. I have a lot of variables from MATLAB that are cartesian coordinates, X Y Z, of points. Is there a variable type I could use built into C? I need to subtract different points and also do other operations on them. Any suggestions?
Thanks,
DemiSheep
Edit:
Ok I have another question. I want to make sure this is a good idea. (But first, with stackoverflow is this how I should post more information to my post, by editing my original post? -Thanks!)
Question:
I have an object with several characteristics. Say it's a car and the car has several different parameters.
Parameters:
Position on map
Altitude (sea level?)
Start position
End Position
Can I use a struct or union (or both?) to have all these parameters inside the car "object" and update the parameters in the object like you would if it was it's own class in like C++ or Java?
Like if I want to calculate the distance the car traveled from the start position to its current position in like a Cartesian plane I could do something like:
distantTraveled = car.position - car.startPosition
Thanks,
DemiSheep
There are no built-in types that will do what you want.
You'll probably have to make your own small struct type such as the following.
typedef struct {
double x, y, z;
} coordinate;
If you're limited to C (rather than C++), you'll then need to build up a small library of functions to operate on these data types.
For what it's worth, I highly recommend looking around to find a library that will provide this type of thing for you. Ideally something specialized to the domain you're working in.
You would use a struct (typedef struct {double x,y,z;} point;) or an array (double p[3]).
If you want to get more clever you could use both by employing a union:
typedef union {
struct {double x,y,z;} s;
double a[3];
} point;
but this comes at the cost of wordier access syntax:
point p;
p.a[2] = 7;
p.s.x = 5;

What techniques/strategies do people use for building objects in C (not C++)?

I am especially interested in objects meant to be used from within C, as opposed to implementations of objects that form the core of interpreted languages such as python.
I tend to do something like this:
struct foo_ops {
void (*blah)(struct foo *, ...);
void (*plugh)(struct foo *, ...);
};
struct foo {
struct foo_ops *ops;
/* data fields for foo go here */
};
With these structure definitions, the code implementing foo looks something like this:
static void plugh(struct foo *, ...) { ... }
static void blah(struct foo *, ...) { ... }
static struct foo_ops foo_ops = { blah, plugh };
struct foo *new_foo(...) {
struct foo *foop = malloc(sizeof(*foop));
foop->ops = &foo_ops;
/* fill in rest of *foop */
return foop;
}
Then, in code that uses foo:
struct foo *foop = new_foo(...);
foop->ops->blah(foop, ...);
foop->ops->plugh(foop, ...);
This code can be tidied up with macros or inline functions so it looks more C-like
foo_blah(foop, ...);
foo_plugh(foop, ...);
although if you stick with a reasonably short name for the "ops" field, simply writing out the code shown originally isn't particularly verbose.
This technique is entirely adequate for implementing a relatively simple object-based designs in C, but it does not handle more advanced requirements such as explicitly representing classes, and method inheritance. For those, you might need something like GObject (as EFraim mentioned), but I'd suggest making sure you really need the extra features of the more complex frameworks.
Your use of the term "objects" is a bit vague, so I'm going to assume you're asking how to use C to achieve certain aspects of Object-Oriented Programming (feel free to correct me on this assumption.)
Method Polymorphism:
Method polymorphism is typically emulated in C using function pointers. For example if I had a struct that I used to represent an image_scaler ( something that takes an image and resizes it to new dimensions ), I could do something like this:
struct image_scaler {
//member variables
int (*scale)(int, int, int*);
}
Then, I could make several image scalers as such:
struct image_scaler nn, bilinear;
nn->scale = &nearest_neighbor_scale;
bilinear->scale = &bilinear_scale;
This lets me achieve polymorphic behavior for any function that takes in a image_scaler and uses it's scale method by simply passing it a different image_scaler.
Inheritance
Inheritance is usually achieved as such:
struct base{
int x;
int y;
}
struct derived{
struct base;
int z;
}
Now, I'm free to use derived's extra fields, along with getting all the 'inherited' fields of base. Additionally, If you have a function that only takes in a struct base. you can simply cast your struct dervied pointer into a struct base pointer with no consequences
Libraries such as GObject.
Basically GObject provides common way to describe opaque values (integers, strings) and objects (by manually describing the interface - as a structure of function pointers, basically correspoinding to a VTable in C++) - more info on the structure can be found in its reference
You would often also hand-implement vtables as in "COM in plain C"
As you can see from browsing all the answers, there are libraries,
function pointers, means of inheritance, encapsulation, etc., all
available (C++ was originally a front-end for C).
However, I have found that a VERY important aspect to software is
readability. Have you tried to read code from 10 years ago? As a
result, I tend to take the simplest approach when doing things like
objects in C.
Ask the following:
Is this for a customer with a deadline (if so, consider OOP)?
Can I use an OOP (often less code, faster to develop, more readable)?
Can I use a library (existing code, existing templates)?
Am I constrained by memory or CPU (for example Arduino)?
Is there another technical reason to use C?
Can I keep my C very simple and readable?
What OOP features do I really need for my project?
I usually revert to something like the GLIB API which allows me to
encapsulate my code and provides a very readable interface. If more
is needed, I add function pointers for polymorphism.
class_A.h:
typedef struct _class_A {...} Class_A;
Class_A* Class_A_new();
void Class_A_empty();
...
#include "class_A.h"
Class_A* my_instance;
my_instance = Class_A_new();
my_instance->Class_A_empty(); // can override using function pointers
Look at IJG's implementation. They not only use setjmp/longjmp for exception handling, they have vtables and everything. It is a well written and small enough library for you to get a very good example.
Similar to Dale's approach but a bit more of a footgun is how PostgreSQL represents parse tree nodes, expression types, and the like internally. There are default Node and Expr structs, along the lines of
typedef struct {
NodeTag n;
} Node;
where NodeTag is a typedef for unsigned int, and there's a header file with a bunch of constants describing all the possible node types. Nodes themselves look like this:
typedef struct {
NodeTag n = FOO_NODE;
/* other members go here */
} FooNode;
and a FooNode can be cast to a Node with impunity, because of a quirk of C structs: if two structs have identical first members, they can be cast to each other.
Yes, this means that a FooNode can be cast to a BarNode, which you probably don't want to do. If you want proper runtime type-checking, GObject is the way to go, though be prepared to hate life while you're getting the hang of it.
(note: examples from memory, I haven't hacked on the Postgres internals in a while. The developer FAQ has more info.)

Resources