- 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
hey, I like the idea of the static analysis, but WTF (why TF) use a proprietary tool that not all of us can get our hands on without spending $$? Why not just use lint???
I see Coverity has a free trial, but I really would rather not whore my info to them and be on their awful mailing list forever more.
Admin
As soon as I submitted that, my question was answered by the banner ad for Coverity at the top of the page. I'm sad.
Admin
But "near their use" is a variable not easy to determine. At the beginning of the scope is MUCH easier to find.
If you're looking at the last line, how easy is it to find the definition of foo? Well, it's not easy at all.
But there's no reason to make the code harder to read and require some IDE, require the reader to move the mouse over every variable to find its type, etc. That's just making things harder for no reason at all.
Which is a thing I consider evil. It increases clutter A LOT. How often haven't I seen a C++ program with one huge block of mixed declarations and statements? Pretty often. And it's pretty hard to read that way.
No, any remotely decent compiler will tell you when you use a variable uninitialised. Forcing people to clutter their code and make it unreadable to "reduce the chance of using an uninitialised variable" really is a non-argument.
Admin
Admin
Um, maybe because too Lint isn't at all the same thing?
They both look for potential bugs, but that's about as far as their similarity goes.
Admin
strlen returns the number of characters in the string not including the terminating null, so there isn't enough space allocated by new for strcpy to append the null.
Boom, instant buffer overrun.
Admin
No that was intended... Or to be more exactly, it doesn't fall under the hack which allowed the first sample. A text literal is a const char[], which can be implictly, converted to a const char* or (if necessary) a char*. Note that the last conversion only applies to a text literal. So, the expression (blah?"foo":"bar") as a whole is a const char*. (actually, since both literals are the same size not conversion at all is needed, so it might even consider it a "const char[3]". Regardless, the expression as a whole is not a text literal, and therefore cannot be converted to a "char*".
For the most part, I agree, but one must consider degrees of distinction. There is about a 80-90% overlap in "C Knowledge" and "C++ Knowledge". And much of the 10-20% difference is C++ not allowing the kind of idiomatic/sloppy programming that C only allows because the first C compilers had to run in 32K and were more concerned with code generation than syntax checking.
Oh well, you suddenly went from competent debater to idiot/jackass. No, my definition of a well-written C program has nothing to do with C++ compiler. Apparently, you don't really understand the concept of "well-written". Let's take for example, the code you posted before:
The fact that this passes through a C compiler does NOT mean it is "well-written". Properly, it should be:
"const" has been part of the C language for 18+ years, so it's about time you actually learned this language you defend so much. In fact, "const" was added to the language at the same time the parameters were added to function declarations (Previously, that would have had to be written as "void foo();") So you can't even fall-back on claiming that it's legacy K&R C code --- The sample was written wrong to start with.
No Comment --- I'll just let the readers judge with is "harder to read, much harder to maintain and overall puts the code in a lot worse condition"
C++:
C:
Addendum (2007-04-25 13:45):
No that was intended... Or to be more exactly, it doesn't fall under the hack which allowed the first sample. A text literal is a const char[], which can be implictly, converted to a const char* or (if necessary) a char*. Note that the last conversion only applies to a text literal. So, the expression (blah?"foo":"bar") as a whole is a const char*. (actually, since both literals are the same size not conversion at all is needed, so it might even consider it a "const char[3]". Regardless, the expression as a whole is not a text literal, and therefore cannot be converted to a "char*".
For the most part, I agree, but one must consider degrees of distinction. There is about a 80-90% overlap in "C Knowledge" and "C++ Knowledge". And much of the 10-20% difference is C++ not allowing the kind of idiomatic/sloppy programming that C only allows because the first C compilers had to run in 32K and were more concerned with code generation than syntax checking.
Oh well, you suddenly went from competent debater to idiot/jackass. No, my definition of a well-written C program has nothing to do with C++ compilers. Apparently, you don't really understand the concept of "well-written". Let's take for example, the code you posted before:
[/code]
The fact that this passes through a C compiler does NOT mean it is "well-written". Properly, it should be:
[/code]
"const" has been part of the C language for 18+ years, so it's about time you actually learned this language you defend so much. In fact, "const" was added to the language at the same time the parameters were added to function declarations (Previously, that would have had to be written as "void foo();") So you can't even fall-back on claiming that it's legacy K&R C code --- The sample was written wrong to start with.
No Comment --- I'll just let the readers judge with is "harder to read, much harder to maintain and overall puts the code in a lot worse condition"
C++:
C:
Admin
This code compiles without warnings on GCC 3.4 and 4.1 (gcc -W -Wall and g++ -W -Wall). I would consider both of them to be "remotely decent".
As for the rest, I guess again we disagree. I don't find myself needing to know the type of a variable and not being able find the declaration at all frequently, and think the readibility and other benefits outweigh those times.
Admin
RTFA:
"Of course, you don’t have to use my skeleton solution, but it’s there for you if you’d prefer. For the Linux folks out there, you may use the mostly equivalent GTK skeleton solution."
Good thing its not a test of reading comprehension!
Admin
Now, the funny thing is that if I replace blah by a constant 1, GCC won't throw an error on this code, which is why I wrote it as I did.
I'll agree that C allows many, hmm, suboptimal expressions to be used. But many of those are considered legacy and bad style. C++, however, in many cases encourages sloppy and obfuscated programming. Sloppy programming would include making declarations at random places, obfuscation would be for example operator overloading.
I'm sorry you see it that way. My point is still that they're not the same language. Many of the "features" of C++ which I dislike are also the ones that make things not compile with a C compiler.
No, I completely agree there, the prototype for foo() should indeed have const for its parameter.
But there are a fewseperate issues here and I think we're talking a bit besides each other:
I think for 1 and 3, we agree or mostly agree.
For 2, I think we don't. Let's take the most common C as C++ showstopper: Implicit casts from void *. I really, really can't agree that explicitly casting the return value of malloc() makes code more "well written."
Let's take another example:
Is this code badly written?
Oh, I do know, use and preach the use of const very much!
I think you misunderstood me a bit. I didn't defend the non-use of const, I was saying that these differences mean that a C program does not compile as C++.
I do not know when const was added to C, but I do know about parameter-less prototypes (obviously). However, string literals are still char * in C, so the sample is not wrong. Wrong in C++, yes, not wrong in C.
Besides that I think that your C code is ugly, I'll just give one competition: Count the amount of function calls in the C and the C++ code, tell me which functions are called and where to find them. Thanks :)
Admin
Well, that code will give you at least one warning with -Wall:
The reason you're not warning about the usage of the uninitialised variable is that GCC cannot perform this without optimisations being enabled, if you compile with at least -O, you also get this warning:
And besides that, I have my own opinion of the quality of GCC 3.4 and 4.1, and it's not good, but I'll spare you from hearing about that ;)
Nothing wrong with disagreeing. Maybe the difference is that I work a lot with code other people wrote, while I guess you mostly work with code you wrote? Forgive me if I am wrong :)
And while finding the type might not be something you do that often, it's still something you do and have to do when you validate code. Another thing you also must do is to be able to distinguish declarations from statements, something which is harder to do than is necessary in much of the code I read and validate.
Admin
Really? And I thought I was being clear and explicit. At least I didn't do anything like
And I firmly believe if read by someone completely unfamiliar with either language, the function of the C++ is more readily understood. ("Strcpy? Shouldn't that have a vowel somewhere?")
How would you write it prettier?
A valid question -- to a point. Ignore the C++, and just tell me how many you think there are in the C code. Exactly how complex is malloc or strcat or printf? And even if you know the complicity of your library now, who's to say it won't change on the next release of your compiler. Those simple function names hide vastly complicated code --- exactly as the + in my C++ example.Now, to get back to the original argument, in most contexts, I'd consider "C/C++" to mean "The C & C++ family of languages" inwhich I'd include C# and Java.
P.S.: I appreciate the change in tone. I appologize for the "jackass" comment.
Admin
sprintf
Yow.
Admin
Operator overloading is another place where I disagree, at least when used judiciously. Is it obfuscation to allow +, -, etc. to work on a complex number or a rational number class? If anything, I think having to write cplx_add(a, b) instead of a + b is obfuscation.
Or for a less conventional approach, what about using operator overloading to essentially build an abstract syntax tree of an expression? For instance, I have a program that I wrote that interfaces with a SAT solver, and you have to feed it expression trees for expressions like "(x and y) or (x and z)". In C, generating this tree would look something like this:
Or, if you prefer,
Which looks a little like an ugly version of Lisp if you're into that.
Whereas I can write
(I wouldn't indent it like that if it weren't for the max line length here)
Actually right now I can be even more brief:
but I think that's gone a little to far; too many implicit conversions.
In the above the differences between the C version and my version are relatively small, but imagine how the C version would look for what I can write as
Some would probably say this is an abuse of operator overloading, but IMO this has dramatically improved the readability of the code. And that's really one of the goals of overloading.
Finally, operator overloading is almost required if you want to be able to write generic functions like, say, min or max that operate on both primitives and user-defined types.
I agree there.
This is a downside; C++ hides code behind your back. For instance, I'm not even sure of the answer to that question, because there are a number of places that I'm not sure whether constructors are implicitly called.
Admin
Someone unfamiliar with aeither language should not be writing in either language. It would just lead to seriously buggy code. And that's an uncommon and not very useful scenario anyway, IMO. It's much more likely that someone who knows both languages is gonna read it.
Both examples are pretty simple, so there's not much room for confusion there anyway. The problem really arises when you've got really complex C++ code, deeply nested inheritance, multiple functions with the same name, operator overloading, etc. Debugging your way through a complex C++ program is very hard and I'd say it's bordering impossible to follow the flow of a complex C++ program without a debugger... which in my line of work is something you aren't always afforded.
Well, most of the code would go towards a utility function I wouldn't mind having seen in the C library. Someone might consider the utility function "hairy" or "complex", but IMO (and I don't intend to be rude when I say this) that would just show that the person doesn't know C. Anyway, here goes:
Yes, but those function calls all have a clearly defined function and are clearly distinguished from things that are not function calls. I was also only talking about functions called directly from the code.
In the C code I count 8 function calls, and that took me no time or brain power to figure out.
In the C++ code I count 11, and that number took a little bit more thinking and time to get to.
So, if someone writes on his CV that he knows C/C++, would you consider him competent for a C# programming job? ;)
Ditto. I guess sometimes I just get too passionate about a discussion ;)
Admin
Yeah, that's because I am a C++ programmer. ;-) I saw the warning when I compiled with gcc and fixed it, but then forgot to paste the updated version.
Interesting... I think I knew that GCC requires optimizations sometimes but forgot. That's... kind of stupid. I realize they are trying to speed up compilation, but if you use -W -Wall (which itself is somewhat silly... shouldn't -Wall turn on, I dunno, "all" warnings?) I want warnings.
I don't know how good GCC is on an objective scale. There are some things that I know that other compilers do better, but they tend to be somewhat esoteric stuff like produce nice output with -S. And they seem to have better C and C++ language support then, say, VC++ 6, though that isn't exactly a gold standard of compilation either. They're also by far the biggest compiler in the OSS community, which means that they are almost a necessary target for some apps.
It's sort of a mix. I definitely do mostly work with my own code, but I'm also doing a fair amount of stuff with existing C++ code bases, and I have done some Linux kernel programming in the past. (That was when I missed RAII in C...)
(Speaking of which, there's a WTF to submit to the site.
Admin
Yeah, geez, if it was he'd probably already have won by now...
Admin
[quote user="Foobar"] C:
[/quote]Besides that I think that your C code is ugly, I'll just give one competition: Count the amount of function calls in the C and the C++ code, tell me which functions are called and where to find them. Thanks :) [/quote]
It's doubly funny because the C++ version he posted allocates several extra strings that it doesn't need. As well as the fact that the C version should have used snprintf()
He kind of proved your argument with the A + ", " + B + "!" yay for allocating 3 extra string objects!
Admin
You don't actually work in the real world, do you? Purely academic?
Admin
For the contest, is writing a C (or C++) app that acts as a web server legal? Then we could write our own hacky web servers with a browser for the UI. Sounds fun!
Admin
There are two WTF ways to approach this: the academic way, and the enterprisey way.
The academic way follows this scheme.
The enterprisey way follows this scheme:
A FFC is an important tool, hence reliability is a major issue. We therefore need a clustered solution with failover.
Each key of the calculator is best represented as a class, each key subclassing the "Key" class. As you may want to have the numeric keys colored differently, there should also be intermediate classes NumericKey and OperatorKey. Same for the display, which should be implemented as 7-segment LCD displays.
For interface, we need some sort of AJAX.
The generation of numeric displays should be a HTML TABLE of generated images. The generation of these images is delegated to a developer group specialising in Perl, and they will use Boutell's GD library from CPAN. The value for each digit will be FTP'd to the interface/display server (running LAMP on a Beowulf cluster of some sort) from the main calculator server farm. The images for the keys are of course generated from a specification received from the Key class value objects stored on the calculator server farm. This is done through a webservice, with each key represented internally in an EJB. Pressing a key calls the webservice, which calls a method on the EJB, which sends an XML representation of the Key value object on the JMS queue to the BPM engine. Did I forget to say the calculator server farm needs to run BEA WebLogic Integration? The actual operation of the calculator is modelled in the BPM language of WLI. The resulting display is continuously posted by FTP'ing (again, XMLized representations of) Digit value objects to the interface/display server. A cron job here ensures that the when the response page is generated, the correct digits will be displayed.
To develop this calculator, we need three developer teams, one for the LAMP frontend, and one for the BEA backend, and one for developing the integration layer inbetween. Two DBAs, fifteen PMs, two application architects, an operations architect, a managerial advisory board, top-level external contractors/consultants for developing the Business Logic in WLI, and then add the usual 25% overhead to be safe. For running the FFC service system, we need a 24/7 manned operations centre, with two Unix admins (Solaris and Linux experts) at any time, a "service desk" call centre, and a backup tape robot with its own support department. And of course we'll have to have the whole project setup ISO 9000 and ISO-20000/ ITIL certified, this adds another ten man-years right there, plus exorbitant consultant fees. Changing the color of a key of course will require modification at all levels, and require thorough change management and redeployment of 90% of the systems. Such a moderate change should be achievable within a window of 6 months, give or take a planning period latency of at least three months.
Before this Four Function Calculator enters service, 85% of the components will be obsolete, unfunctional or out of support, and will need replacement, modification and/or therapy. Which brings us to phase 2 of the Four Function Calculator service, a project one or two orders of magnitude larger than phase 1 described above, due to the rising cost of Enterprise-grade hardware and software, and other factors. Cost of Phase 1: Zillions. Cost of Phase 2: Gagazillions.
-Sin Tax (perfect enterPrisey IT Architect (pePITA) wannabe.)
Captcha: sanitarium
Admin
Corollary: C++ works by quickly making shit out of C.
-Sin Tax
Admin
Another way is to pass the expression (with a suitable wrapper) into a C compiler and have that dynamically compile up a module that contains a function that evaluates the expression. Then you can dlopen() the linked module, get the address of the function from within it, call it, and get the value out, assuming the user hasn't done an "expression insertion attack" on you. (Come to think of it, I've done very similar things in the past. But at least the function there was computationally heavy and came from a large FORTRAN library and the C code was application-specific glue...)
For added fun, write the function in such a way that the code is actually C++ and Boost and requires a full implementation of both in order to build correctly. Indeed, if you do it right, you'll have constructed something that is incredibly slow to operate and which stands a chance of breaking utterly when deployed almost anywhere. :-)
Admin
I do? Where?
I'm assuming that you mean that 'A +", "' creates one new string, while the "+ B" would create another, and the '+"!"' create the third, but, as I didn't show the implementation of std::string, there's no way to state that definitely. It's quite possibly to write a implementation of string::operator+ which would allocate only one string new string for the series of pluses. (And yes, I have written such an implementation).
Admin
Admin
Man... "olympiad" is the term for THE TIME BETWEEN TWO OLYMPIC GAMES!
So when can we expect the actual games?
Admin
How about a calculator that generates emails and waits for the answer? For example, multiplying 12 by 25 would generate a jpeg of 25 lines of 12 matches (or were they toothpicks) on a wooden table, send it to Rain Man, and wait for the answer. Of course, the calculator doesn't work when Wappner is on.
Admin
Admin
Graah! I know C# but not C/C++! It's a pity, because I had a great plan: The program would count the number of buttons pressed, and use that to determine what test case it's on, and what should be displayed. Alternatively, I could have it display the answer but immediately clear the display, because there is no requirement that the answer be outputted long enough to be readable.
Admin
Hm, I don't think the dictionary definition or common usage would agree with you on that one (lots of counterexamples for you there).
Admin
No academic implementation would EVER be in C++, would it?
However, modifying one of the van Wijngaarden grammar examples in [Cleaveland&Uzgalis 1977] to do the job should be fairly easy, and convincing as well. And yes, this would imply unary arithmetic.
-Sin Tax
[Cleaveland&Uzgalis 1977] J. Craig Cleaveland and Robert C. Uzgalis Grammars for programming languages Elsevier (1977)
Admin
Here's a good (bad) design that maybe someone with some free time can implement:
From C++ invoke via COM and VB6 Component DLL, then use the .NET Framework COM Interop to invoke a C# component. Write unmanaged code in C# to do the work. Pass results back to VB and then back to C++ through the component DLL layers.
This should get you on the medal stand.
Admin
I'll just put all the code in one line to gain the extra points.
captcha: pinball
Admin
You forgot to mention, "new is not a keyword, so it's treated as an identifier. Boom, instant syntax error." The correct answer to their question as to why the new operator is crashing would be "what new operator? all operators in C have existed since 1978."