Base 10 arithmetic is really easy to write when you need perfect multi-digit precision for functions like add, subtract, multiply. Divide is a little more tricky but not too bad and you always have to incorporate rounding. I actually do this for my own personal financial stuff. Keeping integer dollars and integer cents separate works pretty well. Keeping double integer dollars is not very hard either. I found a book at a library long time ago with instructions for doing, don't laugh too hard now, multiple digit calculations on a mechanical adding machine. It was an old book but still informative. If the adding machine could do 8 digits, then you could get it to do 16 digits (like multiply operations) following those instructions. On a modern computer though, once you got to the 16 digits you could then double again to 32 digits, etc., etc. Of course there are more direct ways though that I use myself now.Apples and oranges to the nth degree -- two completely different situations.
Writing maintainable code and writing secure code are two very different aspects of programming -- you can do one without the other, though secure code that is also well-written code is far more likely to be more secure in actuality.
Writing code that compiles (or preprocesses) to your example may well be justifiable in performance critical code running on resource-starved platforms. But code such code does not need "magic numbers" to achieve that goal. At the very least, reasonable constant-like macro definitions should be used to indicate what each term means. Not only would that make the code much more readable, but it would also make it much more maintainable since those values probably differ from one MCU to another.
I can't help but wonder what the reasoning was behind the decision to use C for mission-critical financial industry software. It would seem like there are much more appropriate languages around -- in particular, languages that were developed with performing base-10 arithmetic exactly as an intrinsic capability as a goal.
If someone insists on using hammers to install screws, the solution isn't to ban hammers, but to teach the people abusing hammers that other tools exist that are more appropriate to the task.
Fair enough, there's a lot of truth to what you say. On the technical point of bit operations though I cannot agree. The 'bit' abstraction does not depend on the CPU itself having the same abstraction. C does offer a 'bit' abstraction and when field ordering, alignment etc are well defined, this does work. But it could have been syntactically cleaner and treating a bit as a type is the natural thing to do, why the C developers implemented it the way they did is likely lost to history.That is NOT what they are being taught at university. What you are almost certainly seeing there is the result of dealing with legacy code (and legacy programmers) at that company coupled with the extreme cost and risk of bringing existing codebases up to current recommended style guidelines. In the MCU tradespace, this is aggravated by the fact that performance often IS a legitimate factor that trumps readability and maintainability, with the consequence that people in that space often make little or no effort to write the code in as readable and maintainable way as possible within the performance constraints. None of this has anything to do with a particular language -- you can write perfectly incomprehensible code in any language.
Remember, in the early days when a lot of these codebases were getting started, it was actually considered a good thing if you could write code that performed better, no matter how indecipherable it was. This naturally morphed into programmers leveraging this for job security by intentionally writing indecipherable code that only they could maintain because they could get away with it provided they could demonstrate that it performed better than anyone else's. The fact that they could have gotten the same performance will code that was at least far more readable was immaterial. It wasn't until enough software got far enough into its lifecycle that the actual cost of unmaintainable code reared its ugly head strongly enough for companies to start making it a priority -- at least in new codebases.
As for there being no bit data type, that actually makes sense in a systems language intended for high performance -- virtually no CPUs support bit-level operations. The constructs in C are closely aligned with the assembly code that is generated. The big gripe I always had was that it didn't have a rotate operator, which is something that almost every processor has an instruction for.
I started working in "The City" in the mid 80s and quickly realized that computing there was very technical, I met lots of very experienced and knowledgeable engineers. I learned a lot from this experience. There were banks and brokers with lots of money and some very demanding requirements both technical and deadlines.If programmers in the financial industry were using legacy code, they were very likely using Fortran and COBOL.
I don't know what you base the claim that C is a dead language on. C is very much an evolving language -- in fact that's one of the complaints that many C programmers have about it. It was originally intended, among other things, to be a very simple yet powerful language. This allowed compiler writers to target new hardware quickly and the language constructs made it a lot easier to get highly optimized code based on programmer cues. But each new version of the standard extends the language with new features and also tightens down the screws a bit more on undefined and implementation specified behaviors. This makes developing new and updating old compilers a lot more complicated.Fair enough, there's a lot of truth to what you say. On the technical point of bit operations though I cannot agree. The 'bit' abstraction does not depend on the CPU itself having the same abstraction. C does offer a 'bit' abstraction and when field ordering, alignment etc are well defined, this does work. But it could have been syntactically cleaner and treating a bit as a type is the natural thing to do, why the C developers implemented it the way they did is likely lost to history.
I agree too about rotate, an operator could easily be defined (I did exactly that in a proof of concept programming language grammar last year) but C is a dead language poorly standardized, very poor prospects for getting extended, that's another gripe I have.
Although I dislike the C grammar (for a host of linguistic reasons) I will say that the C# team do a fine job with extending the language, since it's initial version 25 years ago, there have been a very steady stream of often impressive enhancements and I don't know of any programming language that can boast of this more than C#, several enhancements stem directly from a desire by others (in Microsoft too) to embrace high performance hardware oriented features (Microsoft did an impressive job too of writing a high performance operating system in C# too).
https://en.wikipedia.org/wiki/Singularity_(operating_system)
You would also have to look at the standards committee's work. An active standards committee that is still updating the standard is the sign of a robust an evolving ecosystem. The C language committee was still in business the last time I checked. C23 will be the next major standards revision, replacing C17. 5-6 years between revisions since K&R in 1976 is a pretty long life for a language and indicative of considerable stability.I don't know what you base the claim that C is a dead language on. C is very much an evolving language -- in fact that's one of the complaints that many C programmers have about it. It was originally intended, among other things, to be a very simple yet powerful language. This allowed compiler writers to target new hardware quickly and the language constructs made it a lot easier to get highly optimized code based on programmer cues. But each new version of the standard extends the language with new features and also tightens down the screws a bit more on undefined and implementation specified behaviors. This makes developing new and updating old compilers a lot more complicated.
There are just far too many things that are "implementation defined" with "vendor extensions", not covered by the (a) standard. So many developers choose an implementation because the variants are so different. C isn't a language anymore, it's a family of incompatible dialects.I don't know what you base the claim that C is a dead language on. C is very much an evolving language -- in fact that's one of the complaints that many C programmers have about it. It was originally intended, among other things, to be a very simple yet powerful language. This allowed compiler writers to target new hardware quickly and the language constructs made it a lot easier to get highly optimized code based on programmer cues. But each new version of the standard extends the language with new features and also tightens down the screws a bit more on undefined and implementation specified behaviors. This makes developing new and updating old compilers a lot more complicated.
They are only incompatible dialects for a very short time. You can pick it up quickly, if you're sharp.There are just far too many things that are "implementation defined" with "vendor extensions", not covered by the (a) standard. So many developers choose an implementation because the variants are so different. C isn't a language anymore, it's a family of incompatible dialects.
https://splichal.eu/gccsphinx-final/html/gcc/c-implementation-defined-behavior.html