- 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
Oh please. The biggest WTF ever is how overloading of shift operators got incorporated into the c++ standard.
Admin
No, the comments make it believable. What you're looking at is the work of a highly advanced practicioner of the "voodoo" or "cargo cult" school of programming. Its philosophy is based on eschewing all attempts to understand language constructs or APIs . Instead, you adapt known receipes, i.e. look through other people's code, take snippets that do things vaguely like what you need, put them together and then fiddle with it in trial-and-error fashion until it works.
Admin
Admin
Actually he made it triangular. With sharp edges.
Hopefully it run over him.
Admin
It's in C, yes?
This means that you can't have a variable declared except at the start of a code block, i.e. usually just after a {
e.g.
void my_function(void){
// Can declare here
int var1;
do_something();
// Can't then declare here
int var2;
so, clever* coders realised that you can force the compiler to create a code block like so :
void my_function(void)
{
// Can declare here
int var1;
do_something();
// Now, it's valid!
{}
int var2;
no, no, no, no, no etc.
Sam
* For 'clever', insert your own descriptive expletive.
Admin
Yeah, I like this don't-know-that-sprintf-exists stuff. Here's another great example using Oracle's "to_char" function which I've found on a production system, too:
<FONT face="Courier New">EXEC SQL at db_xyz
SELECT TO_CHAR(:amount,'999999990.V99') INTO :str_amount FROM DUAL;
strncpy(str_amount, str_amount+1, 12);</FONT>
Note the strncpy to get rid of the leading blank.
HAND
Torsten (from Germany)
Admin
Damn, what I was thinking of was this.
void my_function(void)
{
// Can declare here
int var1;
do_something();
{
// Declare here
int var2;
}
Nothing like todays wtf. Sorry folks, am very tired.
SamAdmin
man asprintf
Admin
It isn't, but those spurios pairs of braces apparently trick his C compiler into thinking a new block has started and allowing variable declarations. That's probably what's meant by that strange comment "make the variable".
Admin
This is not "overloading of shift operator". It would be if the default behavior of that operator in that case would be to shift.
Most operators have no meaning and can't be used by default on classes, so you can just assign any meaning that you deem useful.
The fact that thes operators have a default implementation for badiv integer types that shifts them doesn't mean that it cannot have a different meaning for something else.
Yeah, operator overloading can be missused. As this very website painfully demonstrate every day, you can write asinine crap in any language.
Listening to C++ detractors, it's like c++ code always use totally counter intuitive operator overloading all over the place, which is quite not true. When C++ code is ugly and hard to maintain, it's rarely for this reason.
And by the way, I challenge you to explain how the common usage of << as a shift operator and as a streaming operator can be ambiguous and hard to distinguish (barring the fact that you only rarely ever need to shift integer values anyway).
Admin
Of course it's shorthand for multiply(vector1, vector2), and you already know perfectly well what that evalutates to, don't you?
Admin
Oh my god, kill the "coder" please... [:|] The sad thing is, he was able to make it compile, I wonder how much time he spent only to find the SEEK_SET/SEEK_END values...
This piece of junk reminds me of some code I encountere a few years ago, it was smth like:
char *ptr = malloc(1024*1024*10); // Make sure we have enough memory reserved
if (!ptr) return "";
sprintf(ptr, "[%02d:%02d:%02d %04d/%02d/%02d -- %s\n", hour, min, sec, year, month, day, incoming_parameter);
return ptr;
The size of the buffer I remember very well, it was 10meg of memory it reserved, for a stupid log-function. They didn't understand why the system got slow when a lot of clients connected. In production, this ran in a multi-tasked *nix environment, with normally around 100 concurrent instances running, which could go up to 1000+ when enough clients connected. Since everything was logged, and the machine had 1,5gig of ram, during normal loads, no real problems were encountered, but once the loads went up a bit, welcome to swap-heaven. Once this was fixed, the server could do his job with ease actually not needing more than 512mb...
Indeed... :( Don't like C++ in general. Plain C for straightforward stuff, if it has to be object-oriented, I like to stick to Java. Operator overloading seems nice, but is abused soo often that you can't be absolutely sure what it does. A guy I know once wrote a socket class where "adding" some self-written string-class to it, was actually appending the string to the internal output buffer and send it, while subtracting was only adding to that output buffer. Both returned the original object again. You don't want to see the clever constructions he made with that... Luckily for me (was asked to debug it), operator precedance is the same for all C++ compilers, so I could reconstruct what he was trying to do... Sadly enough, that part worked just fine, so he didn't see any reason to change it...
Admin
Roman.
The next handle would have been FILE1V
Admin
"Cargo Cult Programming". Brilliant! Did you coin that phrase?
I'd like to emphasize that there is a distinction between the cargo cult programmer and the programmers that often learn by adapting recipes. The main distinction is that cargo cult programmers eschew understanding, where the learn by example crowd modifies examples in thoughtful ways, trying to increase understanding.
Admin
Assuming that the question was not sarcasm: No, it's from the relatively well-known hacker jargon dictionary: http://catb.org/~esr/jargon/html/C/cargo-cult-programming.html
Admin
Someone ban this clown for putting up sig ads
Admin
When I used Base 1 in school (a math class, CS only cared about Base 2, with mentions of 8 and 16 where it made the base 2 representation easier), we normally had 1 as the symbol.
Though sometimes the professor got creative, so one problem probably used something from the Korean alphabet (Only a mathematician would learn a foreign language just to get a different alphabet), and just to prove he could I think 2 was used as the symbol one day.
In general though, in base-1 math you use 1 as your number, and 0 as the blank. Base-1 is only slighlty different from base-2 with no blank. You cannot do Base-1 math without a blank.
Admin
FSCK this forum software - it can't even evaluate quote blocks correctly! I've been forced to cite in dialogue-form!!! X( Did I forget mentioning that moving the cursor with the arrows is a random affair?! You never know where it will go or what parts lines the cursor refuse to go through... WFT?!
Zlodo: It's not the shift operator here, it quite obviously the streaming operator.
Yeah, its definition of it as a streaming operator isn't hardcoded in the compiler like it's definition as the shifting operator for numeric datatypes, but this is a very specious argument.
Someone: Oh, operator overloading? That makes everything much more readable.
Zlodo:
I totally agree.
vector = vector1 + vector2 * scale
is barely understandable compared to something like
vector = vector1.add( vector2.multiply( scale ) ).
RevMike: So tell me, what does vector1 * vector2 evaluate to?
Whatever you've defined the *-operator to do on the data types in question. It is up to you to use operator overloading judiciouisly.
Paraphrasing anon: "Of course it's shorthand for vector1.multiply(vector2), and you already know perfectly well what that evalutates to, don't you? "
All programs -including operators- are collections of symbols and the manipulations of these, symbols chosen for the convenience of the programmers. The symbols used for bitshifts pictographically imply moving something in a particular direction. Why couldn't this movement be toward a target/recipient (as in stream operations)? Why can the pictograms used for bitshifts have no other intuitive meaning in other contexts? Normally, human beings are experts in decoding contextual meaning in social situations and natural languages. Why wouldn't programmers too be able to handle this? There are other cases you chose not to pick on like distinguishing between bitwise and logical and by single and double ampersands, or using * for pointer declarations, dereferencing and multiplication. It is all a question of convenience and becoming habituated. Conceptually, using the same symbols for bitshift and stream operations is not only unproblematic but also appropriate. All good programmers get accustomed to this *immediately*.
Funny, first Zlodo said
then two posts later KoFFiE says
which was a good example in case of what he hinted at: prejudices and misguided idealism, perhaps coupled with some "see no evil" preferences with his particular Favorite Language (tm).
Admin
Not sarcasm. I'm familiar with "jargon.txt", but I forgot about that entry.
Admin
Some people don't like to use +=
I believe its a matter of prefrence much like ++
Admin
I'm the "someone" who started the whole thing, mostly for fun.
C++ operator overloading, like the C pre-processor and C++ mutliple inheritance, are double-edge swords. When used judiciously by a true expert they can be wonderful tools. When used by less skilled practitioners, the risk of injury is great.
Java, for example, eliminated these features to make the language safer from programmers. Of course, then Sun turned around and introduced J2EE, a spec that a true expert architect can play like a virtuoso, but that anyone less will turn into a WTF.
Maybe that should be Java's motto: "Java: making mediocre programmers look good and mediocre architect look bad!"
Admin
What you should do is use an IDE that supports MathML (or alike), and will do the convertions into code for you.
Admin
No idea if it works.
Admin
I did guess that because of the smiley, but I just like debating (or flaming about) this C++-is-evil-because-you-can-overload-operators thing :)
Admin
It can actually be done in a way that could arguably be considered close to the frontier between neat and convoluted in C++:
And then
double u=v1*v2; // you clearly want a scalar product
vector u=v1*v2; // you clearly want a cross product
works.
Admin
I would normally apologize for the double post, and messing up in the first place and stuff. But since we can't preview, can't edit and the code tag is broken, I would dare say that it's not my fault in the first place. Here we go again without the fucked up html entities showing up:
It can actually be done in a way that could arguably be considered close to the frontier between neat and convoluted in C++:
class VectorProduct;
class Vector
{
(snip)
const VectorProduct& operator*( const Vector& othervec )
{
return VectorProduct( *this, othervec );
}
(snip)
}
class VectorProduct
{
private:
const Vector& m_v1;
const Vector& m_v2;
public:
VectorProduct( const Vector& v1, const Vector& v2 ) :
m_v1( v1 ),
m_v2( v2 )
{
}
operator double()
{
// return the dot product between m_v1 and m_v2
}
operator const Vector()
{
// return the cross product between m_v1 and m_v2
}
}
And then
double u=v1*v2; // you clearly want a scalar product
vector u=v1*v2; // you clearly want a cross product
works.
Admin
> We'll use ">" for "pairwise multiply" (we'll return a vector) then we'll drink a beer
> and laugh at the poor saps who'll be maintaining our code when we move on.
For those who bash operator overloading, I only have the following reply, in Java:
public int multiply (int v1, int v2)
{
return v1 + v2;
}
Yes, exactly.
Admin
Please, kill this guy.
Admin
Why would anyne do that? We have a built in integer multiplication operator, and the method you describe isn't even a static method. This makes very little sense...
Maybe what you really wanted to say is this...
public class MyInt
{
private int theValue;
.... constructors and other methods skipped.
public int multiply(MyInt v2)
{
return theValue + v2.theValue;
}
}
The problem with operator overloading - and even C++ fans admit this - is that it is possible to overload an operator in an unexpected way AND it not be obvious to a maint. developer that there is even a method call involved. Java, by eliminating operator overloading (ignoring the String +), insures that the developer always knows that there is a method call involved.
Admin
I can't speak for others, but in my experience of working on several, often WTF-ridden and quite large C++ code bases, I don't think I ever seen operator overloading that would give an operator an unexpected meaning.
Basicaly, I can't remember any case where I encountered any overloading besides equality, arithmetics for custom mathematical types (like vector and matrices), streaming, and dereferencement in smart pointer implementations.
Not to say that it doesn't happen, but it doesn't seem like such a common occurence as people seem to make it.
The WTF I see most often in C++ code seem to be more lke stupidely huge classes, useless classes, stupidely huge functions, juggling with pointers, duplicated (but different) implementations of the same things, and generally doing simple things in an hopelessely convoluted way.
Note that all of these WTF except the pointer stuff can be, and probably are, done with any OO language.
Admin
Hey, how about a rating system for each day's WTF? Here's my score:
Overall Absurdity: 150 (Just look at it.)
Negative Side-Effects on Application: 175 (filling up disk space, memory leaks, overall slowness)
Originality: 125 (I've seend other beginner programmers doing some of these things)
Density: 190 (almost every line of code is a WTF)
Tilt: 200 (bonus points for the comments)
Total: 840 "Brilliance" Points
Admin
I'm surprised no-one's commented on the gem at the end of the function yet...
So, we take the address we were told to write the string to (string_write_to), cast it to a long (then add 0 for no readily apparent reason), implicitly casting it to an int as we assign it to stopHere. Then add on the size of the output. Finally, if that number isn't zero, we null-terminate the string in two exciting and subtly different ways.
How can this go wrong? Well, if sizeof(int) < sizeof(char*), we'll crash when executing ((char*)stopHere)[ 0 ] = '\0';
But more amusingly, for stopHere to be equal to 0, we'd need to have written exactly enough text to the string to have got to the end of the memory (or that subset of it addressable by an int) and wrapped around. Well, I'm glad this genius was smart enough to check for that!
Admin
If it were just square it might be fixable, but this one has edges pushed partway into a fractal dimension.
Admin
Nah, I think this one is contrived. Google for vfprintf, and the first page also describes vsnprintf.
And this line too:
double bignumberjustincase = ftell( FILE11 );
Almost makes too much sense.
Admin
you forgot the parentheses and the comma
Admin
Not everyone knows about sprintf. A friend of mine was a good developer, one of the better developers I've know in recent years. Would create strings out of strcpys and strcats and even wrote his own int to hex function. I would through and rewrote all his code one day with sprintfs as it was easier to read one line than 5...
He asked me "what is this sprintf you are using? and does it work?"
Admin
Ah no - that should be 840 "Brillance" points.
Admin
You're idea is interesting, but it's faaaaaaar too complicated for the simple mind of my guy :)
Admin
I tend to agree in principle because this very point is frequently cited (often by poor programmers) as justification to overload well-known operators to do esoteric tasks.
Even with that in mind though, I find operator overloading one of C++ greatest strengths because it allows a good programmer to "correct" the default action of an operator from an otherwise dangerous situation. eg.
struct tdata
{
char* some_string;
};
struct tdata str1;
struct tdata str2;
str1.some_string = strdup( "a nifty one reference string" );
str2 = str1;
The above code is legal in both C and C++. The "default copy operator" cannot be overridden in C and cannot be disabled - thus, the compiler can never be instructed to prevent the situation. In C++, one can override the "=" operator and provide in it a "strdup" that ensures every "struct tdata" gets it's own unique copy of the data.
Obviously this is a contrived example, but it illustrates my point. Scenarios like this crop up quite frequently.
My biggest gripe about C++ is that they introduced an ambiguity that C doesn't have; in C a pointer and an array reference are handled in the same way (syntax-wise) though they are considerably different things. C gets away with this because one cannot produce a single object that has 2 potential type definitions. This was retained in C++ for backwards compatibility but now a single object can have more than one implicit type conversion. By overloading the array operator [] and also providing an automatic pointer type cast, the compiler can no longer resolve which of the conversions is the correct one for the scenario where the object is referred to through an array operator - is it intended to implicitly convert through cast and dereference or should it called the overloaded array operator?
The programmer must resolve the scenario manually by calling the desired operator via call-syntax (eg. object.operator [] ( parm ) ) which is now harder to read and more verbose than the old system! Worse, neither of the two "operators" can be used directly, making them enssentially worthless.
Again, a contrived example, but it shits me often.
Admin
Oh no! He misspelled the variable: temorary_file_name_name.
Admin
OMG It's a fake (Obviously)
Admin
I dislike operator overloading on two grounds :-
1. I cannot create arbitrary operators. I can only overload existing operators. This implies strongly to me that operator overloading is just that - an overloading of existing behaviour.
2. The resulting code doesnt look like C++. Operator overlaoding cannot be used to change the way parameters are passed to functions (or methods). So, than some constructor syntax tricks, one quickly has to revert to "regular" c++ syntax, using brackets and parentheses.
It looks like another language has been wedged into c++ purely for dealing with streams... fuck, if we are going to start incorporating features from other languages I'd much rather that c++ had been extended to allow multiple returns (int a,b,c=func()). and/or co-routines and generators. And having first class virtual functions (I dont know how to describ this, basically declaring a function (or method) should be synomonous with declaring a function pointer with that name. A simple reassignment would revector all calls to that label).
All simple things I've only seen in script languages like LUA or Python, but I cant see any impediment to their implementation in a compiled language.
Admin
Not that it is something I would necessary want to do, but I think that with a creative redefinition of the comma operator, it could be done :)
Admin
As someone who programs Java for a living, I can tell you that that is EXACTLY what's being done with it (except for most of the pointer juggling, of course).
However, I still shudder at the thought what people writing that kind of code could do when they are given operator overloading and get excited about its possibilities...
Admin
To be fair, overloading the shift operators was incorporated into the standard early on because it seemed like a cool example of things that can be done with operator overloading. At the time few (and no popular) languages supported operator overloading, so there was no general experience to suggest that abusing it is a bad thing. The standard committee has not done so since then, suggested that as soon as it was realized that operators should not be abused they stopped.
I recall that someone on the standard committee once saying that they regret introducing it, but I can't find any reference, so take it with a grain of salt.
Admin
:blink blink:
/rubs eyes
:blink blink blink:
I honestly cannot choose between laughing and crying; part of me wants to meet this guy and get him to explain how he came up with this travesty, and part of me just wants to take a baseball bat to him. Holy Jesus Tapdancing Christ, I've seen bad code before, but that's just...just...
I am screaming inside, and the one line that has me going bugfuck more than anything else is
double bignumberjustincase = ftell( FILE11 );
because there's just no fucking excuse for that. If you know ftell() exists, then you also know it doesn't return a double, dammit! That just takes this to a whole new dimension of pain and misery.
This guy has way bigger problems than not knowing about sprintf().
Admin
Sweet.
What about this:
vector u=(v1*v2)*v3;
And your answer may include the words "that should be a syntax error".
Admin
Aw man, did I go and forget those "<sarcasm>" tags again? Could have sworn I had them around here somewhere.
Admin
Well, it should be possible to make such ambiguous constructs a compilation error by making the operator* for a VectorProduct private. Then casting would be needed to disambiguate:
vector u = (double)(v1*v2) * v3, or
vector u = (vector)(v1*v2) * v3.
But this is ugly as fuck and defeats the purpose of defining custom operators for readability. That's why I prefer the more straight forward and more readable in the end solution of using a different operator for the cross-product. After all, mathematical notation does so as well, for the same reason.
Admin
I think you're missing the point. He wants to format some string data into another string. Pipes ain't needed. If he's too stupid to use sprintf(), he's to stupid to be programming.