|
Extracting magic numbers as named constants is usually a good idea, but orthogonal to the question of whether an underscore separator is helpful or not. It absolutely is helpful if you're dealing with number with mure than 7 or 8 digits. There's a reason we use commas (or periods in continental Europe) to break numbers into groups of 3 digits: it makes it much more obvious when a digit is missing (or erroneously present).
|
|
|
|
|
fair enough. So:
#define SPEED_OF_LIGHT_M_PER_SEC 299,792,458
I understand your point, but I abhor magic numbers in code even if I know what they mean. I hate magic functions, and don't get me started on hideously complex macros that cannot be debugged.
Hex constants are okay as well, since I can transpose the bits in my head while reading - but I can see the benefit of breaking up long hex strings when you are masking say a 64 bit value.
The ultimate goal is to avoid errors.
Charlie Gilley
“They who can give up essential liberty to obtain a little temporary safety deserve neither liberty nor safety.” BF, 1759
Has never been more appropriate.
|
|
|
|
|
charlieg wrote: The ultimate goal is to avoid errors.
Yep! And I agree with you that magic numbers run counter to that, since there's no visible, verifiable logic within them - you just have to somehow know that it's correct. When I was learning 68000 assembly in the 1990s, I'd read freely-available source code and see moves to and from arbitrary memory addresses for device I/O etc, and wonder how often people accidentally used the wrong address (or one that may only be valid if your machine has exactly 512kb RAM).
Where possible I'll try to push back on the inscrutability a bit, like defining
SECONDS_PER_DAY as
60*60*24 instead of
86400 .
|
|
|
|
|
C# binary literals:
const uint bitmask = 0b0010_0000_0000_1100_0000_0001_0000_1111; The underscores are useful, no?
Software Zen: delete this;
|
|
|
|
|
I'd use hex.
modified 19-Aug-24 11:34am.
|
|
|
|
|
The binary literals are handy for hardware register bits. This is especially true when the documentation is written by a hardware engineer who documents things by bit numbers rather than masks. Defining this sort of thing with hex is okay, but it takes more time when reading.
Software Zen: delete this;
|
|
|
|
|
VB has datetime literals, I'd find them more useful in my work.
|
|
|
|
|
C won't ever get up-to-date as C proponents don't want anything modern.
It's not like system languages get left in the dust though, Rust is having some exciting evolution.
|
|
|
|
|
Yeah, and what makes it worse is that C is use everywhere. So now there are huge committees involved, so things (even if they did happen) will take a while to get ratified and accepted.
Jeremy Falcon
|
|
|
|
|
It's not (only) that. C++ is driven by a commitee and those guys managed to create a (mostly) modern, pleasant programming language. Rust is driven by a commitee. It's less about commitees and more about specifically C, it attracts a certain kind of people and that certain kind of people keep C the way it is.
|
|
|
|
|
Ruffnik wrote: it attracts a certain kind of people and that certain kind of people keep C the way it is. Gotta agree with you there, buddy.
Jeremy Falcon
|
|
|
|
|
We'll eventually die off and leave you with it as well as the COBOL.
Charlie Gilley
“They who can give up essential liberty to obtain a little temporary safety deserve neither liberty nor safety.” BF, 1759
Has never been more appropriate.
|
|
|
|
|
So, curious question... even if you are trafficking in .c files, why aren't you using a C++ compiler to compile your C code?
Even in embedded environments, C++ is preferred to C. If you must strictly conform to C++ only as better C, and avoid polymorphism, exception handling and RTTI, you are still left with one very powerful tool at your disposal - templates!
Using stupid template tricks, you can easily strip your number of the thousands separator, or indeed, any delimiter such as the '-' (dash) in sweet Jenny's phone number.
It might look something like this:
#include <iostream>
#include <string>
#include <algorithm>
std::string removeThousandsSeparators(const std::string& formattedNumber)
{
std::string result = formattedNumber;
result.erase(std::remove_if(result.begin(), result.end(), {
return !std::isdigit(c);
}), result.end());
return result;
}
Here is an example of how it might be used:
int main()
{
std::string formattedInput = "1,234,567";
std::string strippedNumber = removeThousandsSeparators(formattedInput);
std::cout << "Formatted input: " << formattedInput << std::endl;
std::cout << "Stripped input: " << strippedInput << std::endl;
return 0;
}
If you dislike the idea of having to quote your value, you can also add a pre-processor macro to handle that as well:
#define STRINGIZE(x) #x
You can then use it like so:
auto strippedNumber = removeThousandsSeparators(STRINGIZE(1,234,567));
Keep in mind, all of this is done at compile time, so there is no performance penalty.
When there's a will, there's a relative.
|
|
|
|
|
Stacy Dudovitz wrote: So, curious question... even if you are trafficking in .c files, why aren't you using a C++ compiler to compile your C code? To be honest, habit. Back in the day I adopted the when in Rome mantra, as in if I'm gonna do C just use a C compiler to help make sure I don't do anything "non-C" in it.
That's the only reason. Now I've just done it so long it's just what I do.
Stacy Dudovitz wrote: Here is an example of how it might be used: Per my understanding, if I used the C++ standard libs I'd have to link to the C++ library as well, in conjunction with the C libs. So, I would incur a penalty when it came to runtime requirements if I did that.
Stacy Dudovitz wrote: Keep in mind, all of this is done at compile time, so there is no performance penalty. The out of the box thinking is awesome. Great post.
Stacy Dudovitz wrote: When there's a will, there's a relative.
Jeremy Falcon
|
|
|
|
|
"Per my understanding, if I used the C++ standard libs I'd have to link to the C++ library as well, in conjunction with the C libs."
The only time I now use C/C++ is in embedded work. That generally means running on some kind of RTOS, and more to the point, limited flash RAM.
I mention this because, at least in the embedded world using a complier like Eclipse (or similar), I can and often need to fine tune which libraries I link with.
As a general rule in embedded development in C++, we typically eschew the standard library in favor of speed and size. That means grabbing specific code from the Standard Library for code like the example I gave above. In fact, it is much more common to grab the source for specific calls and just include the source code file, rather than linking to a whole library.
Example: I have my own collection of open source implementations of function calls like itoa , printf , strcat , etc.
In the Windows/Mac/Linux world, I don't think there is really any appreciable difference even if you bring in other libraries.
Note: It's a good thing to keep in mind that if you require the entire library to deploy, the compiler doesn't link to the whole library, but rather only links to the necessary code it references. What that means practically, is depending on what library calls you make/link to, the performance hit is often negligible if you choose to use the Standard Library from the compiler as opposed to bringing in your own source as needed.
Equally important to remember is that when you use the STL part of the standard library, no such limitation exists. Everything required is generated at compile time, and there is no linking to any external code.
So to summarize, if you use the C++ compiler just as a better C compiler, AND you don't make calls into the library that are not implemented as templates, you get the best of all worlds.
|
|
|
|
|
Alice Cooper wrote a song about being "stuck" called Lost in America
Quote: I can't get a girl
'Cause I ain't got a car
I can't get a car
'Cause I ain't got a job
I can't get a job
'Cause I ain't got a car
So I'm looking for a girl with a job and a car
Don't you know where you are
It's not really my cup of tea, and yet the catch 22 situation perfectly describes where I'm at right now.
If I incorporate my new font engine into GFX, I break UIX, which I use to send GFX to the screen.
Rebuilding UIX is not feasible at this point, as I'll get overloaded with tasks and I can't do that much work in tandem with other open issues on my primary project
The whole project is like this.
I need to break my pixel class and my draw destinations as well. That breaks thousands and thousands of lines of code, including potentially (but not definitely) my new font classes.
I'm absolutely buried right now and considering taking a different approach - ground up rewrite, heavy on the copy and paste from the old codebase.
I'm so lost.
Check out my IoT graphics library here:
https://honeythecodewitch.com/gfx
And my IoT UI/User Experience library here:
https://honeythecodewitch.com/uix
|
|
|
|
|
You can bewitch a broom to do some of the carrying. Then split it again for added bandwidth. Profit.
|
|
|
|
|
honey the codewitch wrote: considering taking a different approach - ground up rewrite, heavy on the copy and paste from the old codebase. Sounds like it may be the easiest way to approach the situation. Have fun (if possible)! Just think of the limitations with the old approach that you are overcoming! That might bring a smile to your face!
|
|
|
|
|
Why does it feel like a failure though?
Meh. I guess I am just beating myself up over it. If it wasn't maintainable it wouldn't have lasted for as long as it did, I guess, but then other than feature adds and some minor cross platform compatibility fixes I haven't had to do much.
Check out my IoT graphics library here:
https://honeythecodewitch.com/gfx
And my IoT UI/User Experience library here:
https://honeythecodewitch.com/uix
|
|
|
|
|
[???] Maybe because you kick yourself in the butt for not thinking of the constraints you are now facing when you originally designed the project? It is easy to be hard on yourself, from personal experience. [???]
Go with the flow. If the easiest thing is to do what you are thinking of, smile, take a break, possibly do something else, then get back at it when the mood strikes.
Have fun!, and good luck with it! If I had your skills it wouldn't have taken me so long to do some of my projects!
|
|
|
|
|
I appreciate the vote of confidence.
Check out my IoT graphics library here:
https://honeythecodewitch.com/gfx
And my IoT UI/User Experience library here:
https://honeythecodewitch.com/uix
|
|
|
|
|
Yep, been there with the editor that fixes warnings found by my C++ static analysis tool. Should each line of code be a separate string, or should the entire file be one big string? This went back and forth a couple of times until I settled on the latter, and each time it caused upheaval in the work that had gone into it before. I had no previous experience to draw on, so I had to play around with both approaches until I could decide which one was better.
|
|
|
|
|
Rich woman, bad cough! Is that to much to ask.
I actually have a very good mate.
A home without books is a body without soul. Marcus Tullius Cicero
PartsBin an Electronics Part Organizer - Release Version 1.4.0 (Many new features) JaxCoder.com
Latest Article: EventAggregator
|
|
|
|
|
Yes. While working in Waco maintaining a large electronic health record code base (This was years before the American Recovery Act mandated it.), Micro$oft Windows was doing a major upgrade from Windows 2000 to Windows 7. Since the code base was built starting in the 1990s and long before I joined the company, there was a fair number of Windows API changes that had to be worked in, and this is the killer, a huge amount of duplicate code and reliance on the side-effects of various subroutine and function calls.
The "common code" was a huge DLL that took forever to load and it contained code that was only occasionally used.
My boss, who learned to program in the Navy over twenty years earlier, was one of the programmers who originally built the program. While he was a good programmer, he moved into management and his skills became very rusty and out of date. He could not see why the existing code had to be changed.
This left me with the dilemma: update it on my own time without telling him or try to patch the code and pray that nothing breaks irrevocably.
I came up with a plan:
- I dropped the duplicate subroutines and functions, then recoded the calls to use the ones that remained. I hunted down all of the dependencies upon side effects and removed them. Many were functions that returned a single value of True or False, but modified other data. These I changed to return a data record with the data changes. I released this update to the huge common code DLL.
- I split the common code DLL into a three level structure with all the non-UI Windows API calls in the bottom layer. Depreciated API calls, of which there were many, were replaced with the current ones. The code to set up for API calls, such as letter generation, print formatting, data base record construction and whatnot in the middle layer as multiple DLLs. The top layer contained the business logic, with separate DLLs for
Mental Behavioral Health, Mental Retardation Developmental Disabilities, insurance processing, billing, and client demographics. I released this revised common code as an update. I received praise from the clinicians because the whole program loaded much faster. My boss provided no feedback.
- I split the main UI code removing rarely used paths to separately called programs. The main UI code handled all of the windows that everyone used. The separate programs handled billing and report generation, behavioral health unique logic, and developmental disabilities unique logic. I released this in stages, and again the loading time decreased.
- When my boss decided on a date to update to Windows 7, he asked (finally!) how long it would take to convert the code base. I told him that, with the recent updates currently in place, I could be ready in two weeks.
While the cutover was ongoing, I did have to maintain two versions of the bottom layer of DLLs, but that was not overly onerous. The field crew could reinstall the final version with a simple command line.
The whole thing went so smoothly, that my boss was amazed. He finally looked through the code and was instantly lost when he found the code for loading and running multiple independent modules. He blew a gasket - his and his buddy's "elegant solution," which had morphed into spaghetti code was almost totally gone, although most of their code remained. He could not do much to me at the time: I was the clinicians' hero.
When I was asked (not by my boss!), I told people I was hired by my boss' predecessor as a software engineer, not just as a programmer.
__________________
Lord, grant me the serenity to accept that there are some things I just can’t keep up with, the determination to keep up with the things I must keep up with, and the wisdom to find a good RSS feed from someone who keeps up with what I’d like to, but just don’t have the damn bandwidth to handle right now.
© 2009, Rex Hammock
“If you don't have time to do it right, when will you have time to do it over?” - John Wooden
|
|
|
|
|
CP is up and running again - hopefully for a long time - and even letting me log in!
"I have no idea what I did, but I'm taking full credit for it." - ThisOldTony
"Common sense is so rare these days, it should be classified as a super power" - Random T-shirt
AntiTwitter: @DalekDave is now a follower!
|
|
|
|
|