How to structure complex projects in C?

I have a little more than entry-level C skills, and would like to know if there are any de facto "standards" for structuring a complex application in C. Even based on a graphical interface.

I have always used the OO paradigm in Java and PHP, and now that I want to learn C, I am afraid that I might misstructure my applications. I do not understand on what guidelines modularity, isolation, and dryness with a procedural language should be respected.

Do you have any testimony? I could not find any application platform for C, even if I do not use frameworks. I always found good ideas by looking at their code.

+63
c project-management
Mar 19 '09 at 7:22
source share
9 answers

The key is modularity. It is easier to design, implement, compile and maintain.

  • Define modules in your application, such as classes in an OO application.
  • A separate interface and implementation for each module that is inserted into the interface is only what other modules require. Remember that in C there is no namespace, so you need to make everything in your interfaces unique (for example, with a prefix).
  • Hide global variables in the implementation and use read / write access functions.
  • Do not think in terms of inheritance, but in terms of composition. As a rule, do not try to simulate C ++ in C, it would be very difficult to read and maintain.

If you have time to learn, see how the Ada application is structured, with its required package (module interface) and package body (module implementation).

This is for coding.

For maintenance (remember that the code is one time, but you support it several times) I suggest documenting your code; Doxygen is a great choice for me. I suggest also creating a strong regression test system that allows you to reorganize.

+42
Mar 19 '09 at 7:37
source share

This is a common misconception that OO methods cannot be used in C. Most of them can - it's just that they are a little more cumbersome than in languages ​​with task syntax.

One of the foundations of robust system design is the encapsulation of implementation behind an interface. FILE* and the functions that work with it ( fopen() , fread() , etc.) are a good example of how encapsulation can be used in C to set up interfaces. (Of course, since C does not have access specifiers, you cannot ensure that no one looks inside the struct FILE , but only the masochist does this.)

If necessary, polymorphic behavior can be performed in C using function pointer tables. Yes, the syntax is ugly, but the effect is the same as virtual functions:

 struct IAnimal { int (*eat)(int food); int (*sleep)(int secs); }; /* "Subclass"/"implement" IAnimal, relying on C guaranteed equivalence * of memory layouts */ struct Cat { struct IAnimal _base; int (*meow)(void); }; int cat_eat(int food) { ... } int cat_sleep(int secs) { ... } int cat_meow(void) { ... } /* "Constructor" */ struct Cat* CreateACat(void) { struct Cat* x = (Cat*) malloc(sizeof (struct Cat)); x->_base.eat = cat_eat; x->_base.sleep = cat_sleep; x->meow = cat_meow; } struct IAnimal* pa = CreateACat(); pa->eat(42); /* Calls cat_eat() */ ((struct Cat*) pa)->meow(); /* "Downcast" */ 
+27
Mar 19 '09 at 7:47
source share

All good answers.

I would add only “minimize data structure”. It may even be simpler in C, because if C ++ is “C with classes”, OOP tries to encourage you to take every noun / verb in your head and turn it into a class / method. It can be very wasteful.

For example, suppose you have an array of temperature readings at points in time, and you want to display them as a line chart in Windows. Windows has a PAINT message, and when you receive it, you can skip the array that performs the LineTo functions, scaling the data as you convert it to pixel coordinates.

What I saw too many times, since the diagram consists of points and lines, people will create a data structure consisting of point objects and line objects, each of which is capable of DrawMyself, and then make it permanent what it somehow " more efficiently "or that they may possibly be able to mouse over parts of the diagram and display the data numerically, which is why they build methods in objects to deal with this, and that, of course, involves creating and deleting even more objects.

Thus, you get a huge amount of code that is well read and just spends 90% of the time managing objects.

All this is done in the name of "good programming practice" and "efficiency."

At least in C, a simple, effective way will be more obvious, and the temptation to build pyramids is less powerful.

+11
Mar 19 '09 at 13:16
source share

GNU coding standards have evolved over several decades. It would be nice to read them, even if you don't follow the letter. Thinking about the points raised in them gives you a more solid foundation for structuring your own code.

+10
Mar 19 '09 at 7:45
source share

If you know how to structure your code in Java or C ++, you can follow the same principles with C code. The only difference is that you don’t have a compiler on your side and you need to do whatever you need, manually.

Since there are no packages or classes, you need to start carefully designing your modules. The most common approach is to create a separate source folder for each module. You must rely on naming conventions to differentiate code between different modules. For example, the prefix of all functions with the module name.

You cannot have classes with C, but you can easily implement Abstract Data Types. You create .C and .H files for each abstract data type. If you prefer, you can have two header files, one open and one closed. The idea is that all structures, constants and functions that need to be exported fall into a common header file.

Your tools are also very important. A useful tool for C is lint , which can help you find bad odors in your code. Another tool you can use is Doxygen, which can help you create documentation .

+3
Mar 19 '09 at 7:47
source share

The number rule for complex applications: it should be easy to read.

To simplify a complex application, I use Split and Conquer .

+2
Mar 19 '09 at 7:28
source share

Encapsulation is always the key to successful development, regardless of the development language.

The trick I used to help encapsulate the "private" methods in C is to not include their prototypes in the ".h" file.

+2
Mar 19 '09 at 12:46
source share

I would suggest reading the tutorial in C / C ++ as a first step. For example, C Primer Plus is a good reference. Looking through the examples, you will give an idea and an idea on how to map your Java code to a more understandable language, for example C.

+2
Sep 13 2018-11-11T00:
source share

I would advise you to check the code of any popular open source C project, for example ... hmm ... Linux kernel or Git; and see how they organize it.

+1
Mar 19 '09 at 7:27
source share



All Articles