Question

When programming in Java, I obviously keep related code in classes, organizing a class structure, hierarchy etc to maximize code reuse.

Now I am starting to use C, and am a little confused as to the best way to organize C code in a modular manner. Obviously I am aware of headers and source files, but am somewhat at a loss when it comes to maximizing code reuse in C.

So, how do people organize their code in a language such as C which obviously is not supportive of OOP.

Was it helpful?

Solution

The two languages are different in that java is more modern and designed for OOP

C is older, and is and is a proceedural language. Because the languages are different, the way we program is generally different and so is layout.

C programs have headers (and function prototypes) in the .h and the functional code in the .c file.

In terms of modularity, you can still follow similar patters to java in the way that you section off your code. The general rule of thumb is that one file should do one thing, i.e. string_parser.c should only deal with string parsing. list_sorter.c should deal with list sorting etc.

In terms of code reuse - things like "utility" files are good so reusable useful code can go in the one C file and included where needed. You should never have to duplicate code in C, so if you find yourself copy/pasting functions put it in a centeralised file and include it in multiple places.

Write generic functions! keep you functions simple and open so they are less specific, that way you can reuse your functions.

My advise is to keep your Java code layout knowledge in mind, but also check a good C guide. http://www.doc.ic.ac.uk/lab/cplus/cstyle.html

Generally good project design will help you work out the file layout / structure of the project.

OTHER TIPS

Speaking about main style difference between Java and C I'd like to say this is not OOP absence.

It is generally wrong to think about C like about 'just older' language. It is completely different languages and its nature is completely different. Let say Java is not so perfect in handling low level and this will be always like this because Java is intended to provide safety for application developers. C does not have such usability but grants you more control over things around with appropriate responsibility.

Main advantage of C over Java is distance between interface and implementation. Just illustration: when you have header, actually you have interface concept and it is really interface. You can link completely different modules implementing the same interface based on headers. Well, you will no language control over such things :-) and they are really unsafe. Feel the difference from Java.

In C you can implement OOP approach based on structures with pointers of functional type to method implementations. More, this way you receive something like 'runtime flexible OOP' as this binding is subject of initialization or even runtime changes. It's near from reflection... but far more faster and dangerous.

If you look for good C best practice, check for Linux kernel sources. This code evolves in accordance to modern C best practices and is probably best illustration of pretty large C project with high quality.

Hope this will help.

I tend to think like this:

  • The C equivalence of a java class should be in a pair of .c/.h files. Its data (be it private or public) is contained in a struct (preferably declared in the .c file only). Every function declared in the .h file has a pointer to its struct as a parameter. The .h file only needs to contain a declaration of the struct.
  • The C equivalence of a java package is not possible to achieve by anything but locating the files in different directories. However, due to the single global namespace, it is still mandatory to prefix each non-static function and type with something unique, for examle XXXNAME_YYYNAME_ZZZNAME_FunctionName(), where XXXNAME is the name of the company, YYYNAME is the name of the product or library, and ZZZNAME is the name of the subpackage within the product/library. I have noticed that it is in real life not so common that the companyname is used at all, and if the product/library is "small", that is not used either.
  • (Single) inheritance can easily be implemented by putting the "baseclass"'s struct as the first element of the struct of a "subclass". The inheritance structure is however not easily possible to expose to the client without exposing the entire struct.

Example header file:

struct CARLIB_Car_s;

void CARLIB_Car_Drive(struct CARLIB_Car_s *pCar, uint16_t KiloMeters);

Example source file:

struct CARLIB_Car_s {
   uint16_t FuelLeft;
};

void CARLIB_Car_Drive(struct CARLIB_Car_s *pCar)
{
  // ...
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top