|
Thread: Comments for: "Real men program in C"
|
|
|
Posts:
2
Registered:
08/21/09
|
|
|
|
Re: Comments for: "Real men program in C"
Posted:
Aug 21, 2009 10:14 PM
in response to: Caprica
|
|
|
|
As I have written in the past, I believe C++ is generally preferable to C for most applications, embedded or otherwise. I believe that some of the remarks in this thread recommending C over C++ are mistaken. See the details in my latest column at http://www.embedded.com/columns/programmingpointers/219401085
|
|
|
Posts:
1
Registered:
08/27/09
|
|
|
|
Re: Comments for: "Real men program in C"
Posted:
Aug 27, 2009 11:30 AM
in response to: Caprica
|
|
|
|
I remember when the phrase was "Real men program in assembler"! In my experience embedded applications fall into one of two categories, timely real-time and time critical real-time, the difference being 100’s of Msecs response time to 100’s of Nsecs response time. There should be no question that using OOA/OOD is the standard operating procedure used for program design, even for embedded systems. In most of today’s embedded designs we have the luxury of megabytes and gigahertz verse the kilobytes and megahertz available 15 years ago in our embedded targets. Given that, I say that C++ would be my choice for timely real-time applications and C for time critical real-time apps. This is because the designer not the compiler has complete control over fixed verse dynamic memory allocation and other things that go on under the hood of C++. A couple a years ago I was told by a Wind River FE that they once implemented VxWorks in C++ but had to replace it with a C version for timing reasons. I strongly believe that a disciplined designer can use OOA/OOD in their C designs (i.e. a collection of procedures that perform a function or service (class) in a single module, constructors, destructors, etc.). I admit that C may not be the only language for time critical real-time apps but currently has the most development environment support for the widest range of target systems. If you check out the leading tool vendors such as Wind River, TI and Matlab, I think you will see what I mean.
|
|
|
|
|
|
|
Re: Comments for: "Real men program in C"
Posted:
Aug 31, 2009 5:03 PM
in response to: Caprica
|
|
|
|
My CEngine is a new kind of processor that runs C code directly. The parser is written in C# and produces the loads for multiple memory blocks that personalize a small FPGA design to run the code. The objective is to minimize the number of clock cycles so that the maximum function can be done in C rather than HDL. The architecture is not the typical von Neumann nor Harvard Bus so parallel operations overcome the effects of pipeline stalls. The point that C is still alive is very encouraging. I am an old EE, computer guy, self taught C/C++ programmer.
I will appreciate any questions/comments, email kws15@verizon.net
|
|
|
Posts:
4
Registered:
08/31/09
|
|
|
|
Re: Comments for: "Real men program in C"
Posted:
Aug 31, 2009 8:34 PM
in response to: Caprica
|
|
|
|
Paraphrasing somebody's comment on Reddit I would say: "Real men produce good and complete system analysis before starting to program with the most appropriate tool."
A good system analysis makes abstraction of the tools used to implement the system. OOD/OOA are not part of this phase but of the next step which is software architecture and design. If the analysis suggests an important degree of repeatability then an OO approach may be chosen. If not SADT or similar techniques will do it.
Good examples are: WIDOWS OS, structural approach in C. MSFC, OOA/OOD in C++.
Any other approach which bypasses the system-analysis and jumps directly to low-level software design will produce unpredictable results and cannot be cited as reference.
IMHO the C/C++ controversy is just another "religious war" without any real support. Ultimately the common-sense and the market decide. Just as an exercise for all OOA/OOD fans out there: please look up and let me know one popular, widely used OS based on this technology, an OS being the perfect example of an embedded system.
|
|
|
Posts:
1
Registered:
08/11/09
|
|
|
|
Re: Comments for: "Real men program in C"
Posted:
Sep 8, 2009 6:03 PM
in response to: Caprica
|
|
|
|
Real engineers get the requirements, design, select the right tools and solve the problem. When is the last time you changed the oil or spark plugs with a pair of pliers? You can probably do it... but why? Right tool for the job, move on!
|
|
|
Posts:
1
Registered:
09/14/09
|
|
|
|
Re: Comments for: "Real men program in C"
Posted:
Sep 14, 2009 12:43 PM
in response to: Caprica
|
|
|
|
how do you unit test?
I believe higher level languages help you prototype faster your algorithms and have built in unit test tools ike: junit, nunit, mstest.
while i united tested my c code using bash and running different test executables.. a testrunner like those listed above improves speed in development.
http://robusthaven.com/products/Parsing+Expression+Grammar
hence my company is working on a way to convert msil to glib like system.
this is no different on how labview uses graphical environment and generated c code to be compiled by keil tools to target arm.
|
|
|
Posts:
2
Registered:
09/15/09
|
|
|
|
Re: Comments for: "Real men program in C"
Posted:
Sep 15, 2009 4:17 PM
in response to: Caprica
|
|
|
A very refreshing article to read, which confirmed my suspicions. I keep reading articles about the "rise of C++" in embedded development and I just didn't buy it.
DonDiegoDelaVega wrote:
"There should be no question that using OOA/OOD is the standard operating procedure used for program design, even for embedded systems. In most of today's embedded designs we have the luxury of megabytes and gigahertz verse the kilobytes and megahertz available 15 years ago in our embedded targets."
Although this is certainly true in some situations, this is a bit of a generalization. I work for an industrial controls manufacturer that ships hundreds of thousands of units per year. Cost is extremely sensitive and even a difference of a few dollars per unit has a substantial impact on the bottom line. Thus, we are often left with less CPU power, program ROM and RAM than in an ideal situation. There is no way our existing firmware design could be adapted to C++ without a significant effect on system resources.
D_Lundin, your comments are excellent regarding the better suitability of C for real time embedded systems. You had a number of excellent, spot-on points. I did have a comment about one remark you made:
"While there are better ways to solve things in C and C++, macros are still allowed. The only reason to use macros in ISO C 9899:1990 is portable inlining of functions, a minor concern as modern compilers handle this automatically."
The compilers might handle inline functions, but if you need to write strictly ANSI-C compliant code you are out of luck. We follow the MISRA-C (1998) standard for critical real time systems and it strictly prohibits any non-ANSI compliant code. For this reason we do use macros, although any new ones that we define are looked at very closely during code walkthroughs in our Design Review meetings.
But yes, you are right. Macros are very dangerous. When in doubt, parenthesize. 
|
|
|
Posts:
2
Registered:
09/15/09
|
|
|
|
Re: Comments for: "Real men program in C"
Posted:
Sep 15, 2009 4:42 PM
in response to: Caprica
|
|
|
|
I should clarify my last statement slightly. The MISRA-C 1998 standard used by my company (already outdated I should mention) merely states that "all code shall conform to ISO 9899 standard C, with no extensions permitted".
The question, I suppose, is which ISO 9899 standard? As I understand it, inline functions are included in the ISO 9899:1999 standard, which pre-dates the MISRA-C 1998 standard.
|
|
|
Posts:
5
Registered:
10/29/09
|
|
|
|
Re: Comments for: "Real men program in C"
Posted:
Oct 29, 2009 2:31 PM
in response to: D_Lundin
|
|
|
|
The points you made are quite interesting. The proliferation of micros is one indication that the one memory with a few registers architecture is the underlying problem. A lot of programming practice evolved from the days when memory was the most precious system resource. Single chip embedded systems don't utilize the hundred or so memory blocks that are available on chip because of this inheritance.
So, where am I going? We can put all the variables in a memory as registers. We can have separate memories for statement and operand processing. The variables are all the same width, etc. and all the memories can function in parallel with huge bandwidth while simultaneously using minimum clock cycles to do the function. Realtime capability is maximized.
Now, how do we program the chip? With a subset of C that has the embedded no-nos left out. Where do we get it? Use the string manipulation in C#, take the C expressions (strings that end with a ';'), parses them and generate the memory data. Now take a few classes and clock their behavior emulating chip clocks and output a cycle by cycle activity so the user can see the variable values as they are changed and the flow in the hardware. The user can control function call protocol, memory allocation options etc either by setting options or modifying the parser.
Sounds far-fetched, but I have a prototype running.
|
|
|
Posts:
1
Registered:
11/05/09
|
|
|
|
Re: Comments for: "Real men program in C"
Posted:
Nov 5, 2009 3:38 AM
in response to: Caprica
|
|
|
Language is medium to express the desired getting done from machine. C is the obvious as the most practiced language through out the world. If we have alternatives for the end client, we are free move on with more than languages to environments like Java, .net, and many more to offer RAD in future but the core of all remains the same...
we always love short cuts 
|
|
|
Posts:
10
Registered:
10/22/09
|
|
|
|
Re: Comments for: "Real men program in C"
Posted:
Nov 5, 2009 12:39 PM
in response to: D_Lundin
|
|
|
Horrible, unnecessarily complex syntax. C++ is perhaps the least readable programming language of them all. Compare the syntax to Java or C# and you will grimace at the C++ syntax.
The same could be said of C compared to so many other languages. All the brackets and special characters and ^ when you really mean XOR, and % when you mean MOD? And why does "static" mean two different things depending on the scope? It's a matter of getting used to it.
Potential for very inefficient programs through inheritage, templates, STL etc. STL classes will enforce a heap when we don't need/want one.
This is a rubbish excuse for being a dinosaur.  Yet it is one of the oft cited reasons for rejecting C++: you can write inefficient code with it. So what? The same is true of C if you compare it to assembler. High-level abstraction means you're not constantly face to face with machine code, so how do you really know that the compiler is doing?
int i;
some_type array 10 ;
for( i = 0; i < 10; i++ ) array i = 0;
vs.
int i;
some_type array 10 ;
some_type *iter = array;
for( i = 10; --i; ) *iter++ = 0;
*iter = 0;
vs.
some_type array 10 ;
some_type *iter = array;
*iter++ = 0;
*iter++ = 0;
*iter++ = 0;
*iter++ = 0;
*iter++ = 0;
*iter++ = 0;
*iter++ = 0;
*iter++ = 0;
*iter++ = 0;
*iter = 0;
vs.
some_type array 10 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
vs.
some_type array 10 ;
array 0 = array 1 = ... = 0;
And so on. Which would you say is the version that C most encourages? And which is the more efficient? I assure you, they don't all compile to the same code in any compiler I've come across. Bottom line is, whatever language you use, there is always the potential to write code which is very inefficient. No language can write efficient code for you.
However, while C++ allows you to do all the exact same things you can do in C (thus letting you write a C++ program which is exactly as efficient as the next guy's C program) it opens up the door to a whole new class of optimisations that strictly-C programmers can rarely even conceive of.
Some seem to come at a performance cost but more often end up speeding up your code by making it a lot simpler, removing special cases and redundant copies. Boost's shared_ptr is a good example of that.
Others simply enable you to try out more things because your job is so much easier. Imagine a C program which near its core has a linked list of structures. You've painstakenly written 25000 lines of code that make use of that list, but then you realise that your CPU has a data cache and you'd be much better off replacing the list with an array. How motivated would you be to make the change? Then imagine the same thing written in "clean" C++, where all you need to do is replace the list with an array, and standardised container interfaces make sure your code still works the same.
The point is you're way oversimplifying things by suggesting C++ code is inefficient at all compared to C code. A competent C++ programmer will typically write fast, efficient code in less time than a competent C programmer, and in addition the C++ programmer's code will be more maintainable and easier to optimise further.
C++ programs are very hard to port.
This concern is genuine, as is the concern that C++ has failed to standardise common datatypes, making code reuse and collaboration much more difficult than it could have been.
(Of course, the equivalent constructs in C are not standardised, either, they just rarely exist at all because they're so difficult to work with, so the problem is smaller.)
The only part of object orientation that is a must-have in embedded systems is private encapsulation.
Seriously? What about multiple instances of all that privately encapsulated functionality? When someone goes and adds another UART to the system, do you copy your uart1.c to uart2.c and do a search/replace on all globally exposed symbols? What if UART2 behaves slightly differently from UART1? That's a perfect candidate for inheritance (with or without the overhead of virtual member functions). What about a component which is exactly identical to another component, except data words used throughout are 16 bits instead of 8 - template metaprogramming to the rescue.
For embedded software in particular, C++ is the PERFECT compromise of object-oriented possibilities, metaprogramming options, and low-level versatility and efficiency. Sure, there are promising new languages like D, but D is still in its infancy and not yet widely supported.
Also, the most moronic ingredients of C, like for example macros and the way integers are implemented, are not fixed in C++
Macros were not fixed with C++, no, but they were made obsolete. Use inline functions instead, and templates if you want variable type support. Here's a generic swap function, for example:
template
inline void swap( T &a, T &b ) {
T temp = a;
a = b;
b = temp;
}
As for integers, I assume you mean the loosely defined sizeof( int ). Yes, C++ does not address the problem, but you can typedef your way out of it just as you can in C. In fact you can include the exact same header file.
Now, it's true that STL really wants new/delete (and therefore a heap system that provides malloc/free), but you don't HAVE to use STL. C++ is flexible enough that you can write your own containers suited for your particular application. You can write your own memory allocators (or rely on the stack and/or static data), your own smart pointers, your own pooled string class, and whatever. You can even do reallocateable objects using smart pointers if you're afraid of fragmentation.
It's a strange myth that constructors are a security risk. I guess they might be to a developer who counts ensuring proper initialisation of data as a security risk. But in such a case the real security risk would be the developer in question. Innit.
In my experience most embedded developers are not educated programmers, in fact they rarely qualify as good programmers (not that educated = good, but whatever). They come either from an engineering background (having been taught in the 70s or 80s something you might still call "programming"), or they're completely self-taught. Either way they tend to have far too high an opinion of themselves and are completely out of touch with computer science.
The most seriously retarded programming I've seen has come from the embedded industry. I'm tied down by NDAs, but suffice it to say even something as crucial as the encryption on bloody cash handling units is more often than not implemented by complete idiots. Yes, swapping two bytes around in a key gives you some sort of security (sigh), but swapping them back again does NOT double that security. Honest to God, that's a real-life example.
|
|
|
Posts:
13
Registered:
03/03/09
|
|
|
|
Re: Comments for: "Real men program in C"
Posted:
Nov 6, 2009 6:31 AM
in response to: returningTarzan
|
|
|
"This is a rubbish excuse for being a dinosaur. Yet it is one of the oft cited reasons for rejecting C++: you can write inefficient code with it. So what? The same is true of C if you compare it to assembler. High-level abstraction means you're not constantly face to face with machine code, so how do you really know that the compiler is doing?"
The real issue here is the vast amount of incompetent programmers out there. If the language allows something, you can be sure they will use it. This is why we need standards like MISRA that point out what you should avoid. Now when there is a MISRA C++, perhaps there is hope. Hopefully it will become as widely recognized as MISRA-C.
"for( i = 0; i < 10; i++ ) array i = 0;"
This isn't really a good example, as it is hardware-related and not language-related. The reason no compilers will compile that the same way is because the efficiency depends heavily on the structure of the CPU. A compiler for a tiny 8 bit micro will no doubt optimize to a downcounting loop because compare against zero is usually more effective. While a 32-bit Intel PC compiler might optimize based on how the internal cache memory looks like. So there will be completely different decisions based on CPU architecture.
Templates, inheritage etc on the other hand, will by their nature enforce an amount of overhead algorithms no matter hardware. You cannot design inheritage without a certain amount of overhead code, by its nature. Simply: a code without overhead will be more effecitive than with that comes with overhead.
"Others simply enable you to try out more things because your job is so much easier. Imagine a C program which near its core has a linked list of structures. You've painstakenly written 25000 lines of code that make use of that list, but then you realise that your CPU has a data cache and you'd be much better off replacing the list with an array. How motivated would you be to make the change? Then imagine the same thing written in "clean" C++, where all you need to do is replace the list with an array, and standardised container interfaces make sure your code still works the same."
As I wrote in some earlier post, I never questioned the usefulness of modular, object-oriented programming: this is a must. The above is based on the faulty assumption that you cannot write modul-based code in C. The little "class" keyword doesn't do that for you, it is all about your program design. It is quite possible to goof up that linked list in C++ as well. If you have written a linked list code module in C like the one you describe but cannot replace it, it is because you didn't write it as an autonomous code module. This isn't related to the language but to the programmer's design skill.
"A competent C++ programmer will typically write fast, efficient code in less time than a competent C programmer, and in addition the C++ programmer's code will be more maintainable and easier to optimise further."
I don't agree at all. I would label myself competent in both languages, at least I have worked with both languages for 10 years. I am much more effective in C. Because after the program design is done, I can simply write down the program in C, focusing on the sole purpose and functionality of the program without any headache. The same program in C++ will always give you extra work. You end up like this:
"Oh I notice I must use a destructor here. Ach, then I'll need to implement a copy ctr and an assignment operator too. Oh wait, I will need to do this for the inherited class as well. Wait, what will happen with that constructor when I inherit the class. I must fix it... and that copy ctr as well."
At least 50% of your time goes to meta-tasks like that, instead of investing the time in your actual functionality. And that is without templates. Don't get me started about STL... I have never been productive while writing STL code, and it is a real pain to maintain because the STL library has a real talent for making any simple code turn incredible complex, and often buggy because of it.
... "When someone goes and adds another UART to the system, do you copy your uart1.c to uart2.c and do a search/replace on all globally exposed symbols? What if UART2 behaves slightly differently from UART1? That's a perfect candidate for inheritance (with or without the overhead of virtual member functions). What about a component which is exactly identical to another component, except data words used throughout are 16 bits instead of 8 - template metaprogramming to the rescue."
This is a very common situation. If you made the original routine with careful design, you would allow it to expand into an array of chunks of private data and let the caller run the functions like:
uart_init(UART1, ...);
uart_init(UART2, ...);
uart_send(UART1, ...);
uart_send(UART2, ...);
where your uart code module looks like:
typedef enum
{
UART1,
UART2,
...
} UART_TYPE;
static uart_data [X];
void uart_init(UART_TYPE type, ...)
{
init(uart_data type);
}
Inheritance would typically be fixed with function pointers. For example, the uart_send routine may call upon different functions depending on which uart that was used.
The advantage of the above is that I can write that code in 10 minutes. Good luck writing the same implementation with class, templates and inheritance in that time. No, we suddenly talk about one day of work in C++, for the same result in the end. Both the C and C++ solution will likely be as easy to maintain, but the argument for C here is productivity and time to market.
"Macros were not fixed with C++, no, but they were made obsolete. Use inline functions instead, and templates if you want variable type support."
This was already discussed in this thread or the other... C supports inlining as well.
"Now, it's true that STL really wants new/delete (and therefore a heap system that provides malloc/free), but you don't HAVE to use STL. C++ is flexible enough that you can write your own containers suited for your particular application. You can write your own memory allocators (or rely on the stack and/or static data), your own smart pointers, your own pooled string class, and whatever. You can even do reallocateable objects using smart pointers if you're afraid of fragmentation."
You can do that in most languages. I've written smart pointer implementations in C for example. I see no real advantage/disadvantage for C++ here.
"It's a strange myth that constructors are a security risk. I guess they might be to a developer who counts ensuring proper initialisation of data as a security risk. But in such a case the real security risk would be the developer in question. Innit."
This was also discussed earlier, it is not the initialisation itself that is dangerous, but the way data gets corrupted in RAM over time. So the problem itself is a hardware-related one. Avoiding static initialisation is part of defensive programming, and is widely practiced in the automotive & aerospace industries.
"In my experience most embedded developers are not educated programmers, in fact they rarely qualify as good programmers (not that educated = good, but whatever). They come either from an engineering background (having been taught in the 70s or 80s something you might still call "programming"), or they're completely self-taught. Either way they tend to have far too high an opinion of themselves and are completely out of touch with computer science."
I completely agree, this is a huge problem for the industry.
|
|
|
Posts:
10
Registered:
10/22/09
|
|
|
|
Re: Comments for: "Real men program in C"
Posted:
Nov 6, 2009 11:22 AM
in response to: Lundin
|
|
|
The reason no compilers will compile that the same way is because the efficiency depends heavily on the structure of the CPU.
I actually meant, those five examples will compile differently on the same CPU. Even though they express the same operation, they are not equally efficient, and there is no immediate way to tell from just the C code which is more efficient. So you need some knowledge of how a C compiler translates code in order to produce efficient code with it, just as you need some knowledge of C++ and its relationship to the lower-level compiler output before you can be efficient with C++.
A compiler for a tiny 8 bit micro will no doubt optimize to a downcounting loop because compare against zero is usually more effective. While a 32-bit Intel PC compiler might optimize based on how the internal cache memory looks like. So there will be completely different decisions based on CPU architecture.
And this is another advantage of higher-level languages - you move from telling the compiler how to do things further towards telling the compiler what you want to do, giving it more room to fit your code to the target platform. This advantage is greater in C++, and greater still in even more high-level languages like D (with the "foreach" construct etc.).
By the way, in the case of "for( i = 0; i < 10; i++ ) array i = 0" (how do you escape angled brackets on this forum?) the compiler probably wouldn't change to a count-down loop, since you're explicitly telling it in what order to clear the array. It won't reorder anything since that would leave the array in a wrong state if say an interrupt occurs. Of course if it creates a pointer to iterate over the array, the "i" disappears from the body of the loop, and if you're not using i anywhere after the loop, the compiler just might get it right. But the point is if you don't get all those assumptions right you're writing inefficient code, so it's not as if C safeguards against that, even if you use exactly the approaches the language seems to encourage.
You cannot design inheritage without a certain amount of overhead code, by its nature.
You can, though. Inheritance just means you're sharing code between classes. If the specific class is implied when you call a member function there is zero time spent checking whether you're calling a base-class member function or what derived class the call should go to.
When using virtual member functions you have the option of calling the base class and having the call automatically routed to the correct one of several derived classes. That comes at a cost, but the cost is precisely that of looking up a function pointer, which is precisely what you'd use to get the same behaviour out of C (except the compiler has the option of converting to switch type constructs if that should happen to be more efficient).
In fact, inheritance tends to produce smaller code because you're given a good framework for code reuse (within a project - again, C++'s lack of standardised classes compared to Java etc. complicates code reuse between projects, this is true). For instance if you have that SerialPort base class, you will put shared functionality into the base class, and functionality specific to an RS232 into the derived RS232 class, and anything specific to RS485 into the RS485 class. In my experience embedded applications are packed with cases where precisely that type of code reuse is perfectly suited.
At least 50% of your time goes to meta-tasks like that, instead of investing the time in your actual functionality. And that is without templates. Don't get me started about STL... I have never been productive while writing STL code, and it is a real pain to maintain because the STL library has a real talent for making any simple code turn incredible complex, and often buggy because of it.
I've never found those meta-tasks to be painful. And it's fruitful labour, too. You can just ignore the copy c'tor if you know you're never going to use it (or if the automatic one is good enough). If you are actually going to be copying objects, it's not really a meta-task, but a process of defining what an object is if it's a copy of another object (which is not a trivial thing at all so should get some attention whatever language you're in).
There is some overhead in that you sometimes do need to put more planning into your code when you use more advanced features. But the extra effort put into a more OO solution really, really, REALLY pays off in the end, at least such is my experience. Iterators are a pain in the neck, but they do make sense, and they are a very useful tool when they're called for.
I'm currently maintaining a pure-C project which was written with precisely the philosophy you describe. Someone was way too quick to start typing in "actual functionality", and the result is, well, the mess you could expect.
Of course I share your frustration with STL sometimes (I think all C++ coders do), but then I just don't use it when it doesn't offer me the functionality I'm looking for, or the complications outweigh the benefits. And the point especially when you're making a comparison to C is that with C++ you can either use STL, use Boost, create your own framework classes, or fall back on plain-C approaches.
The advantage of the above is that I can write that code in 10 minutes. Good luck writing the same implementation with class, templates and inheritance in that time. No, we suddenly talk about one day of work in C++, for the same result in the end. Both the C and C++ solution will likely be as easy to maintain, but the argument for C here is productivity and time to market.
But, that example is not a complicated thing in C++ at all.
class UART {
public:
UART( ..arguments.. ) { ..common constructor bits.. }
virtual void send() = 0;
};
class RS232_UART : public UART {
public:
RS232_UART( ..arguments.. ) : UART( ..passed arguments.. ) { .. RS232 constructor bits .. }
void send( char c ) { ... }
}
class RS485_UART : public UART {
public:
RS485_UART( ..arguments.. ) : UART( ..passed arguments.. ) { .. RS485 constructor bits .. }
void send( char c ) { ... }
}
.
.
RS232_UART myPort( ..arguments.. );
RS485_UART myOtherPort( ..arguments.. );
myPort.send( 'a' );
myOtherPort.send( 'b' );
doSomethingWithThis( myPort );
.
.
void doSomethingWithThis( UART& port ) {
// This function can send() to port not caring what subclass it is
}
(Plus some optional finetuning like making the UART constructor protected, etc. etc.)
And now you've defined precisely what you want to do. This will implicitly use function pointers in doSomethingWithThis() to find the right class for &port, and where the class is known in the scope, will call the right version of send() directly, automatically tied to the right set of member variables.
Your example left out the structure of the init() function and how you need to switch between different UART_TYPEs all over the place. Not only does switching quickly become less efficient than vtable lookups, you'll have to do it in any place that the functionality of one serial port differs from another.
So think about maintainability: When an RS422 port is added to the mix, in the above you just add another class. When there is no longer a need for RS232 support, you can simply remove the RS232 subclass (actually the compiler does it for you when it's no longer referenced), and the code to deal with it doesn't bloat up the application anymore.
Also, where your code has a single uart_data structure to deal with all types of UARTs, the above approach would not waste space on member variables that are needed for one class of port and not the other.
The class hierarchy reflects a logical hierarchy of UART functionality. The use of objects reflects the layout of the system. What could be easier or more natural to work with? Plus, it's as efficient as a plain C approach (if not moreso) and way easier to maintain.
This project I'm maintaining at the moment has a dozen serial ports, each slightly different to the next, and they're done in exactly the way you describe. No differentiation between types and instances, loads of variables exposed to the global namespace, horrid repetition of code (i.e. bloat and poor maintainability), no logical grouping of code and related data, and so on. OO would have greatly simplified the whole thing and C++ would have greatly simplified the OO.
C supports inlining as well.
I know. I don't consider inlining an advantage of C++, but rather an example of why macros are redundant in both C and C++. They are more redundant in C++ because of templates, though.
I've written smart pointer implementations in C for example.
How? C doesn't provide mechanisms to guarantee that code is called when a variable leaves scope or when memory is released. And you don't have operator overloading and such. Consider Boost's shared_ptr for example:
{
shared_ptr b;
{
shared_ptr a( new Foo( ... ) ); // create a Foo and point to it
a->something();
b = a; // b points to the same Foo
}
a->something(); // wouldn't work because a is out of scope, but..
b->something(); // b still points to the object. So who owns the Foo then?
}
// Ha! Doesn't matter, because b was the last reference, so now the Foo has been
// automatically destroyed. I'm immune to memory leaks, mwhahaha!
Yes, you can do some sort of reference counting in C, and you can have some sort of ownership concept, but an actual smart pointer?
{
Foo *b;
{
Foo *a = (Foo*) malloc( sizeof( Foo ) );
b = a;
}
something( a ); // wouldn't work because a is out of scope
something( b ); // would still work
}
// But now we have a memory leak. How are we supposed to conceptualise the lifetime
// of the Foo structure? How do we know that nobody is referencing it anymore, and how
// do we turn the disappearance of the last reference into a call to free()?
Avoiding static initialisation is part of defensive programming, and is widely practiced in the automotive & aerospace industries.
Sure thing. I avoid it like the plague. But I didn't catch how it relates to constructors?
Sorry for the endless ranting, BTW. I'm just a little bored, you see. 
|
|
|
Posts:
10
Registered:
10/22/09
|
|
|
|
Re: Comments for: "Real men program in C"
Posted:
Nov 6, 2009 11:30 AM
in response to: returningTarzan
|
|
|
On a side note, I hate forums that strip anything that looks a bit like an html tag. 
|
|
|
Posts:
5
Registered:
10/29/09
|
|
|
|
Re: Comments for: "Real men program in C"
Posted:
Nov 6, 2009 11:53 AM
in response to: returningTarzan
|
|
|
|
Before you get too carried away badmouthing what has evolved to the point where geniuses like you are now involved, remember those were the ones that made it work while others were off inventing computer science. They had a job to do and not the luxury of waiting for computer science to mature.
I would sure like to see the hardware that you designed. Also in your spare time would you whip up a hardware simulator that can be used to check out functional behavior in the early stages of design? Or do you just write code and run it with no debug and expect hardware design to be done the same way?
One last thing. Since the compiler does whatever it wants, how do you know if code execution time meets the hardware timing requirements?
|
|
|
|
|
|
|