- Feature Articles
- CodeSOD
- Error'd
- Forums
-
Other Articles
- Random Article
- Other Series
- Alex's Soapbox
- Announcements
- Best of…
- Best of Email
- Best of the Sidebar
- Bring Your Own Code
- Coded Smorgasbord
- Mandatory Fun Day
- Off Topic
- Representative Line
- News Roundup
- Editor's Soapbox
- Software on the Rocks
- Souvenir Potpourri
- Sponsor Post
- Tales from the Interview
- The Daily WTF: Live
- Virtudyne
Admin
I'm glad I did. Sorry if I missed your sarcasm: I work with a bunch of talented people but sometimes deadline lead all of us into phat WTF...
Admin
Can someone explain what the WTF is here?
I am not C or C++ programmer. I have to say that my interactions with a few (certainly not all) C++ old timers were anything but pleasant. Some came across as arrogant jerks; "I can do C/C++, I am the god's gift to programming", "What? you are VB, C#, {any language other than C/C++ } programmer!?!?!! That's not even a language, it's a child's toy, blah, blah, hahaha!!!!"
Admin
Someone converts a mac address to a string WITH COLONS (using sprintf), and then promptly runs the remove colon function to get rid of it. He could simply make the conversion WITHOUT the colon in the first place...
Admin
No less than any other heap allocations.
Nope, it isn't. Standard doesn't guarantee it will be.
Wrong, not in any interesting operation, and correct, but it can smash the stack instead. And if it does so, you'll have no warning.
Using alloca() in this day and age is a WTF, period. It's been deprecated on purpose.
Admin
What it has to do with hardware is for things such as PIC microchips that are programmed in assembly, the GBC that was programmed in assembly, the GBA which is programmed in C. The hardware limits the "level" of the language you can use because of memory/processing limitations.
Admin
<font size="2">Sure. They should replace teaching of character arrays with detailed teaching of various classes and methods for building and parsing strings.
Often programmers who did VB and moved to .NET continue to ignore classes like StringBuilder and methods like Format. They sure will have no clue on regular expressions.</font>
Admin
[:|]
Admin
Erhmm, isn't it pretty standard to display a MAC address with each byte seperated by a colon?
But that wouldn't explain why they needed a function to remove them again of course. Unless the application gets one or more mac addresses from a config file or something, though this admittedly isn't very likely.
Btw, i love working with char arrays :-) Incidently, somebody mentioned that modern string implementations are not based char array. What are they based on then? Linked lists?
Admin
Again: the code explicitly created a String representation of the address with colons, and the IMMEDIATELY called an (inefficient and unsecure) methode to remove the colons - the version with the colons is never used for anything at all. But what makes this a huge WTF is that the method to remove the colons appears to have written specifically to be used there and nowhere else, while all it would have taken to get the same result (without wasting time on writing and running the "removeColons" method) is to remove the five colons in the sprintf format string.
Admin
Such a shame about these little critters called Digital Signal Processors which may have a Minimum Addressable Unit consisting of 16 bits or more. Since the C standard requires that sizeof(char) == 1, and that the result of 'sizeof' be the number of bytes occupied by the data type, these DSP's have to define a 'byte' as being something other than 8 bits (usually 16 or 32 bits). On these platforms even a data type like "uint8" occupies 16 or more bits of memory.
Don't believe me? Check out any processor in the Texas Instruments C54x series.
Admin
Quite a lot of C-functions (I'm tempted to write "all", but there may be exceptions) can be called improperly, and in many cases, the program will crash. For example, strcpy assumes that the first parameter is a pointer to a writeable memory area which is large enough to hold a copy of the null-terminated String pointed to by the second parameter. So is strcpy to blame if strcpy(NULL, NULL) crashes? For that reason, a function named "RemoveColonsFromMacAddrs" should be used for nothing else but the given purpose. (Anyway, the implementation badly sucks)
Admin
Oh Yes! Sorry I didn't see that it was called within the other function...yes total wtf...
Admin
That sounds like a WTF all by itself - as in, "WTF? How can a uint8 contain 0x1234?". (I'd hope the compiler prevents this from happening, actually).
Admin
Hey, "architect" is a noun, not a verb! WTF?!
Admin
Just when you think it can't get any worse, along comes some dumb ass, talks about speed and then repeatedly uses strcat on the same address!
Dude, this has quadratic runtime behavior. Any overhead a string class might incur is easily swamped by the penalty of your moronic idiom.
Admin
Ok, it's been a *long* time since I coded C (or C++ for that matter),but surely there's a replace function?
For the record, in my C++ programming class we were told not to use the String construct, and to use char arrays instead. The reason given for this was that the String class had a load of functionality that we just didn't need and would only get us into trouble. I get the idea that we were supposed to get our heads around arrays before trying out fancier stuff, but I'm sure the "Strings are bad" idea got carried over into real life where using a String would be better.
Admin
@Opt: You are correct, but I think there was a mistake in the original post. This WTF is in C, whereas the String class is a C++ thing. Of course, if the GBA supported C++, it would be reasonable to expect it to support the String class.
Admin
" in my C++ programming class we were told not to use the String construct, and to use char arrays instead."
Now that's a major WTF. If there are teachers like that around, no wonder there is so much badly written and unsafe C++ around.
"surely there's a replace function?"
There surely is in std::string. Actually, a small family of them. (That's overloading for you.)
Admin
I know the perfect solution! Just use the "bConfirm" paradigm from yesterday's WTF, and disallow setting the parameter to "true" anywhere but in the MacAddrToChar function!
Or expand the concept slightly, and introduce a "strCalledFrom" parameter, then check if it's got the proper value of "RemoveColonsFromMacAddr"!
Admin
Can't you throw an exception, catch it and examine the stack backtrace to check if it has been called from MacAddrToChar?
Admin
@Bellingham: Exactly. I can see why they do it - to get across the idea that classes aren't always appropriate - but they should really introduce people to the String class as well.
Admin
Admin
I think somebody has to say it.... "Brillant!"
Admin
Cute. But I think this is C, not even C++, and certainly not Java with its enormous exceptions.
Admin
Once upon a time, I worked out how to persuade this forum's software to do quoting properly from this browser. I've now forgotten it.
Sorry guys. It's not as though I ever do anything as stupid as use the preview button.
Alex: (if you're not bored stiff already by the subject) does 1.2 have anything in its changelog indicating that these problems have been addressed?
Admin
Disagree. It's perfectly acceptable to require that a student do things the hard way in an introductory class. If you're programming in C++, it's VITAL that you understand pointers and memory and arrays and such. Forcing a student to use them in an academic setting is good practice. Of course, as the student progresses, he needs to learn how to use the String class too, and I'd expect that the requirements for the code would change to reflect that.
Admin
"Of course, as the student progresses, he needs to learn how to use the String class too, and I'd expect that the requirements for the code would change to reflect that."
Agreed. It was that bit that was missed out
Admin
I don't follow it that closely, but I'm not very confident it will. I will certainly take a look at v1.2. I wish people would give *honest* reviews of this damn software. Everyone is afraid of offending the authors of it becuase everyone knows the authors of it.
No less, I will take a look at 1.2 (december release they say) . It looks like its a pretty big rewrite, so maybe it's good to just wait around until their bugfix release of 1.25.
Admin
You do realize that "Brillant" means "Bright" in French. While everyone mocks for a missing "i", the french speaking people of Canada know better.
Admin
If you think Paula was being sly and sneaking some French into her Java creation, then you're not so bright.
Admin
Go ask one. Like all of us, I'm sure you have one sitting near you.
Admin
As CS programs across the country, and likely the world, are removing curiculum that involves low-level concepts, we're generally getting a lower grade of a developer. There are surely some very sharp mathmatical minds coming up but if the others can't understand a char array, what prayer do they have understanding why a StringBuilder/StringBuffer is so much better or, as you said, regular expressions?
Admin
What's your point? Why does that make character arrays (which, the last time I programmed in machine code, weren't natively supported by the hardware) needed instead of Strings (generally implemented as a character array)?
To be honest, it looks like you just dumped a bunch of terms you don't really understand into a post.
Admin
If that's the case, it's a horrible thing. If we want to train programmer/operators, they should go to a trade school. CS should not be a 'how to program' study.
I will note that in my CS department, there were two teachers that you could generally take for the core classes. The sweet motherly type that would hold you hand and let you program in VB or the heartless asshole who would mark of 15 percent on a programming assignment if was a millisecond late (literally) and it had to work perfectly to get a grade at all. Most of my peers scrambled to get the easy teacher and never knew their ass from a hole in the ground. I took the tough teacher because he really knew his stuff and I learned a lot from him. But I remember in later courses having to carry team members who couldn't program in C++ and they were juniors.
Admin
This reminds of sales clowns using "leverage" as a verb. It is now in the dictionary as transitive verb but wasn't always.
Admin
<FONT face="Courier New" size=2>well, clearly, the right solution doesn't involve changing the original function. who knows what uses it, and how? is there other crappy code that calls this and expects the colons there?</FONT>
<FONT face="Courier New" size=2>identify the new requirement, and strip out the colons from the mac address there. leave the original function alone.</FONT>
Admin
Two WTFs don't make a right.
Admin
Come on, that's no fun. I like to try to pull the table cloth out from the under the table settings.
Admin
<FONT face="Courier New" size=2>i think there's value in learning some basic string manipulation algorithms using character arrays. it's a simple, fast way to teach about pointers, memory allocation, etc. then you can move on to other things.</FONT>
Admin
<FONT face="Courier New" size=2>jkg? mullet?</FONT>
Admin
"Disagree. It's perfectly acceptable to require that a student do things the hard way in an introductory class. If you're programming in C++, it's VITAL that you understand pointers and memory and arrays and such. Forcing a student to use them in an academic setting is good practice. Of course, as the student progresses, he needs to learn how to use the String class too, and I'd expect that the requirements for the code would change to reflect that."
And I will disagree with you in return. I admire the old-school "work is good for you" attitude, but I feel it misplaced, just as I would feel it misplaced if you insisted that C# coders first started by learning how to code in raw MSIL. (Or whatever the assembler language for the .NET VM is called - I'm not a .NET or C# code myself.)
In an introductory class, I would want to see good habits introduced. C++ needs to be taught as C++, not as an extended form of C. Certainly, pointers exist. Certainly, raw memory access exists. But how much actual requirement is there for that in real-world source code? Relatively little, at least compared to C.
I happen to side with Andrew Koenig in "Accelerated C++" and Francis Glassborow in "Beginner's Introduction to Computer Programming", neither of whom start with C subset. (Both are active members of the C++ standardisation community, btw.)
Once you've got the right handle on C++, then by all means examine the stuff that only library implementors need to know, or what you need in order to talk to external libraries. But the initial approach should teach you safe computing, and it should very clearly indicate when you are dealing with unsafe constructs. Starting out by banning the safe constructs and making you learn the unsafe ones - that's the way to raise another generation of coders who wonder why they get memory leaks and access violations everywhere.
The old saying was that you can write Fortran in any language. The implication of that was that it wasn't a good idea. The big problem with C++ is that it's so easy to write C in it, and almost nobody stops to think whether it's a good idea or not. That's why I considered a course based on it to be a WTF.
Admin
<FONT face="Courier New" size=2>it's exactly like the time grandpa removes his underwear without taking off his pants. lisa asks "how did you do that?" and he replies, "i don't know..." and gets the sad face.</FONT>
Admin
Well there are lots of tricks with #define that I could come up with, but anyone can add them. Try this version:
I'd like to use the comma operator in there, but then it only operates correctly on some compilers.
Admin
not to mention, it helps the developer understand WHY a higher level API does what it does. A greater understanding of an API is never bad.
Admin
No, don't think so.
Admin
Absolutely. There is nothing quite as frustrating as having to clean up code written by a C++ "learner" who missed the forest for the trees. As it happens, I'm currently spending my day-job hours doing just that. I inherited a MFC monstrosity over a year ago and have been maintaining and updating the product since then; I just now finally managed to convince Those In Charge that a virtually complete rewrite is desperately needed. I'm most of the way done with the rewrite now, and I'm breathing easy now that I've actually got C++ to work with.
The old codebase could probably put out a few dozen WTFs all on its own, and many of them are related to treating C++ as C-with-some-pesky-OO-fluff. C-style casts are rampant, many removing specifiers like const. There were a couple of places where a CString was cast to LPCTSTR (const char *) and then the const was cast away (not even with const_cast!) and the data messed around with. Virtually all of the memory allocation is done with malloc() instead of new/delete. Non-POD classes were thrown around wantonly by value instead of using references or even pointers (and they wonder why the memory usage was so ridiculous...). I don't think I saw a single proper destructor, and the original coder had definitely never heard of templates. STL may as well not even exist - it wasn't used anywhere, favoring C-style arrays and very shaky memory allocations instead of std::vector.
There was no encapsulation at all, and 90% of the application logic relied on accessing global pointers via the subclass of CWinApp. The dependencies were so messed up that changing any code file or header would almost guarantee a complete rebuild of the code - which usually took 15 minutes. (I've since made use of precompiled headers and sorted the dependencies as part of the rewrite. There's a net of about 2000 more lines of code now because of encapsulation, and the whole thing compiles from a clean state in under 30 seconds.)
My indirect boss (the owner of the original code) still makes a point of dropping by my cube and scoffing at my rewrite efforts on a daily basis. Fortunately, he's made no genuine attempt to stop it, which means that the code will be much nicer in the long run. I'll be handing it off to another heir soon, and I'm glad to know the guy who takes my seat here will have a decent codebase to write on.
So listen to Bellinghman. Coders need to write C++ in C++, and quit trying to write Fortran in C++. Part of the problem is people who want to bend their current knowledge and tools to fit the job, instead of doing the Right Thing and learning the right tools to do the job. That includes using tools at the right level of abstraction. If the level of abstraction of your data is "string" and not "buffer of bytes," then don't treat the string like a buffer of bytes. Always prefer to treat data according to "how do I interact with this data" instead of "how is this data stored" - elementary encapsulation. Since pretty much all of OO in C++ relies on that kind of judgment, I'm rather apalled that a class would blatantly disregard such an important principle of design.
Apalled, but not surprised. I sat through a rather miserable C++ class once where essentially every topic except for stream IO classes was glossed over and ignored. Needless to say, the few of us who didn't fall apart were the ones who had already been programming for years anyways.
Admin
Trying to continue to generalize...
void RemoveCharacterFromString(char c, char s);
void MacAddrToChar (uint8 macAddrInt, char macAddrStr)
{
sprintf (macAddrStr, "%02x:%02x:%02x:%02x:%02x:%02x",
(macAddrInt) & 0xff, ((macAddrInt + 1)) & 0xff,
((macAddrInt + 2)) & 0xff, ((macAddrInt + 3)) & 0xff,
((macAddrInt + 4)) & 0xff, (*(macAddrInt + 5)) & 0xff);
RemoveCharacterFromString(':', macAddrStr);
}
void RemoveCharacterFromString(char c, char s)
{
if (!s || !c) { return; }
/ ha ha, very funny */
char *t;
for (t = s; *s != '\0'; s++)
{
if (*s != c)
{
if (t != s && *t != *s)
{
*t = *s;
}
t++;
}
}
if (*t != '\0') { *t = '\0'; }
return;
}
Admin
if (isxdigit((unsigned char)*m)) {...}
would be too easy, eh?
Btw, the cast is necessary if *m is a char.
Admin
A character array is generally based on the functionality of the hardware itself. A "char" is one byte, whatever size a byte happens to be. So in dealing with chars, you are dealing with memory in a much more direct manner.
When you do some lower level programming, like coding something designed to run directly on a microcontroller or a PIC or something like that, you usually use C. Generally because that's what it supports. On such hardware, your choice of languages is limited. You can't just put any language onto any piece of hardware, unless you feel like rolling your own compiler.
Admin
Ah, ctype.h... funny, all the prototypes I can find for isxdigit call for an int.