This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

HPs

Let me tell you a story about a guy named Jed...

A long long time ago (pre-ANSI C), in a galaxy far far away I had worked for a company that had to develop internal "C" coding standards and "Jed" worked on one aspect of the standard while I worked on another. We would hold weekly meetings to reconcile our differences. In attendance, we had other professionals for simple sanity checking and to gain insights from different points of view.

Chris was one of our attendees and was a very experienced software veteran who had plenty of code in various satellite systems orbiting our planet today. By then, Chris was in upper management and graced us with his wisdom when he could.

Well during one of our weekly meetings, "Jed" and I got into a simple disagreement on a Rule about header files. We were at an impasse, so we waited for Chris to arrive and have him make the final decision: about five of us professional engineers were in the room.

When Chris arrived, he heard the arguments, and quickly announced that I was right. (Hence, Jed was wrong).

Well, Jed freaked out and wanted to take the guy outside and teach him a lesson! ... Jed was red-faced, quickly stood up, even took a step towards Chris, and said "Chris, lets just step outside and settle this! I am right and you don't know what you're talking about!" etc etc.

The other attendees and I were duly impressed over Jed's technique of handling technical disagreements. Especially with upper management.

Instead of Jed trying to learn that he *might* be wrong, Jed leaped into the confrontation method of getting his way. Bullies do this because they lack the brain-power to reason through a disagreement. It is a childish trait.

Children are at a huge disadvantage when arguing with "an adult" (or somebody who is much smarter than they are) and they will become very frustrated over their strong desire to assert themselves and their inability to win the mental sparring. They will get physical and/or verbally abusive. Some people out grow this, and some don't.

I think Jed showed his 'abilities' quite well. I find that this is true with so many people on so many subjects. I've seen this behavior many times over. I've seen it here on this forum.

When an "Original Poster", asks a question and people try to answer it (after much refinement of the OP's question) you get these side-bar posts where somebody will start attacking another poster's efforts. And I mean 'attack' and not augment or refine.

I don't have a problem with correcting or clarifying others, or even the occasional sprinkling of sarcasm, but when it is ALWAYS devolves into some vindictive vitriol between a brisling poster and the rest of 'us,' I wonder if it is out of ignorance, malice, or some twisted form of self-entertainment. All three of which are adolescent behaviors. (en.wikipedia.org/.../Adolescence)

Since the regular players here are detail oriented and thus they are savvy enough to know who I'm talking about, I don't think I have to name names.

He is critical enough to figure it out himself, so I would expect that the offender would read this and ask himself if he is demonstrating Ignorance, Malice, Entertainment, or is he being an adult and providing a constructive post before he does so.

And, I hope his "Mea Clupea" (en.wikipedia.org/.../Mea_culpa) will be a silent one, because I'm kind of tired of reading his Hostile Postings (HP).

</rant>
--Cpt. Vince Foster
2nd Cannon Place
Fort Marcy Park, VA

Parents
  • Erik: "now I am (I confess) totally lost.
    if you can not use preprocessor directives to make portable, how can you then make it portable, say between little endian and big endian situations, not to mention between different length ints?"

    Vince: "I don't think ANY embedded professional would expect to write in pure 'C'."

    I might manage a truly magnificently portable program slightly larger than "Hello World" if I target a Posix platform.

    In this case, we are arguing (at least mainly) about embedded development.

    So, our programs are not portable. They can't be. But we can affect the cost and time needed to port them to another platform.

    Littering the code with huge amounts of #ifdef will not help, since the cost and time needed to maintain such a monster would be gruesom. But it is a direct approach, and hence the first way a beginning developer learns how to write "portable" - or in this case compilable for multiple platforms.

    A better way is to see what parts of the software that is very closely tied to the hardware, and separate this into separate files. It will not be "drivers", but it is a beginning. When speed is important, the full functionality may be moved to a target-specific file. When speed isn't as important, the code may be splitted in two layers - one that worries about the bits, and one that worries about decisions.

    In some cases, you may then need a few #ifdef in one or two header files to select which set of target-specific functions to use. In some situations you may use the project manager and specify which source files to include in the build. Most often you will be stuck with something in-between.

    So a "portable" program may contain #ifdef, and often have to. But the #ifdef used will not be sprinkled around. They may define a UNPACK32(p) macro that knows in which order the four bytes should be loaded, allowing the send_config()/receive_config() functions to manage without caring about the required byte order. Or, you may have buffer_target1.c, buffer_target2.c, buffer_targetx86.c, ... that contains the implementation of get_u32(ptr) functions, letting the project select the correct function for your active target.

    In the end, the magical factor isn't if the code contains #ifdef, but how the code has been partitioned and how/where any #ifdef are used. The maintainance cost isn't so much affected by a target.h file containing one or a houndred #ifdef. But if I have 50 source files, each with 5-20 #ifdef, then I suddenly have a lot of source files to worry about.

Reply
  • Erik: "now I am (I confess) totally lost.
    if you can not use preprocessor directives to make portable, how can you then make it portable, say between little endian and big endian situations, not to mention between different length ints?"

    Vince: "I don't think ANY embedded professional would expect to write in pure 'C'."

    I might manage a truly magnificently portable program slightly larger than "Hello World" if I target a Posix platform.

    In this case, we are arguing (at least mainly) about embedded development.

    So, our programs are not portable. They can't be. But we can affect the cost and time needed to port them to another platform.

    Littering the code with huge amounts of #ifdef will not help, since the cost and time needed to maintain such a monster would be gruesom. But it is a direct approach, and hence the first way a beginning developer learns how to write "portable" - or in this case compilable for multiple platforms.

    A better way is to see what parts of the software that is very closely tied to the hardware, and separate this into separate files. It will not be "drivers", but it is a beginning. When speed is important, the full functionality may be moved to a target-specific file. When speed isn't as important, the code may be splitted in two layers - one that worries about the bits, and one that worries about decisions.

    In some cases, you may then need a few #ifdef in one or two header files to select which set of target-specific functions to use. In some situations you may use the project manager and specify which source files to include in the build. Most often you will be stuck with something in-between.

    So a "portable" program may contain #ifdef, and often have to. But the #ifdef used will not be sprinkled around. They may define a UNPACK32(p) macro that knows in which order the four bytes should be loaded, allowing the send_config()/receive_config() functions to manage without caring about the required byte order. Or, you may have buffer_target1.c, buffer_target2.c, buffer_targetx86.c, ... that contains the implementation of get_u32(ptr) functions, letting the project select the correct function for your active target.

    In the end, the magical factor isn't if the code contains #ifdef, but how the code has been partitioned and how/where any #ifdef are used. The maintainance cost isn't so much affected by a target.h file containing one or a houndred #ifdef. But if I have 50 source files, each with 5-20 #ifdef, then I suddenly have a lot of source files to worry about.

Children
  • Erik: "now I am (I confess) totally lost.
    if you can not use preprocessor directives to make portable, how can you then make it portable, say between little endian and big endian situations, not to mention between different length ints?"

    Vince: "I don't think ANY embedded professional would expect to write in pure 'C'."

    you are missing the one I refer to
    Mr. Sprat: "Wrapping code in preprocessor directives doesn't make it portable - in fact, it makes it clear that it is non-portable."

    So, our programs are not portable. They can't be. But we can affect the cost and time needed to port them to another platform.
    BRAVO! BRAVISSIMO!

    Littering the code with huge amounts of #ifdef will not help, since the cost and time needed to maintain such a monster would be gruesome.
    BRAVO! BRAVISSIMO!

    But if I have 50 source files, each with 5-20 #ifdef, then I suddenly have a lot of source files to worry about.
    I inherited one of those and the only way I could get it to a level where I could maintain it was to make it far less 'portable' and, as usual, a port never was requested.

    Erik

  • your post is even more interesting for me as I am (still) working on porting C167 code to an ARM. I can port most of the following modules without significant changes: queue(s), synchronization primitives, timers, trace buffer, scheduling logic. There are no preprocessor dependencies - all I did was to change most of the basic types used to unsigned long to get rid of some inefficient assembly. I am still struggling with the target specific features that really make the difference - interrupt handling is so different and apart from that, I just HATE making target specific modules that are a salad of many "target specific" functions.

  • There are no preprocessor dependencies - all I did was to change
    that is what has beaten a dead horse to a pulp in this thread: the contention that you can port without either having preprocessor directives or making changes.

    Erik

  • "...I do not give a hoot about portability..."

    "that is what has beaten a dead horse to a pulp in this thread"

    Looking back through this thread, it would appear that YOU were the first one to mention it !!??

    Why, oh why, oh why then do you insist on writing about it so much?

    Before you get on that high horse (yet) again, realise that I just wrote a rhetorical question.

  • the correct (and complete) quote would be

    all I did was to change most of the basic types used to unsigned long to get rid of some inefficient assembly

    the nature of the modules that I mentioned is that they are platform independent in the sense that they are pure C implementation. I did put some effort into porting them but the implementation details did not change much. what are suggesting? that I would rewrite (and test...) then all the satisfy my crazed desire to cut off 0.5 microseconds here and there?!

  • Erik: "you are missing the one I refer to"

    Mr. Sprat: "Wrapping code in preprocessor directives doesn't make it portable - in fact, it makes it clear that it is non-portable."

    No, I wasn't actually missing it. I was more pondering what to do with it. The question here is what "wrapping" means.

    Use of #define in itself doesn't ruin an otherwise acceptable program. Standard guarding of header files is an example where we are "expected" to use #define statements.

    Abuse of #define can on the other hand (and tend to) produce unreadable code.

    The bad thing is that it can be a fine line between the two.

    If kept together where I expect to find them, then I, personally, see them as useful. If spread out, I see them as evil.

    Maybe Jack uses the word "wrapped" to mean "sprinkled with". Maybe his tolerance level is lower than mine. Some people are of the opinion that the preprocessor should be totally banished. enum and const declarations allows a large number of #define to be replaced with direct language constructs.

    Build systems that allows different targets to have different include directories and that allows easy selection of what groups of source files that should be included in the build can remove the need for a lot of (maybe all) #ifdef.

    But in the end we fall back to the problem of "portable". Exactly what is the definition of "portable" in the current context?

  • the contention that you can port without either having preprocessor directives or making changes.

    but I did make changes! I never contended not to have made any. The code is generic enough to run reasonably well of any modern 16 bit or better processor. the fact that I don't need the preprocessor nor too extensive changes is a demonstration of portability. It was not my intention to write the best possible, most efficient code. I only wanted to reuse well tested, trusted pieces of functionality. with all due respect, if that does not fit into your perception of efficiency - than you must have a great time rewriting just about anything to win a pico-second here and there. no thanks...