- 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
Not us as you in, but us as in me.
;)
Admin
The first bit of code has a slight chance of being the result of somebody too addicted to editing videogames. Particularily, the game "Operation: Flashpoint" follows an almost identical syntax for its 'mini scripts' features.
Either that or it's just coding even more backwards than Visual Basic is to begin with (an achievement with all but the most recent of versions <<).
What the heck is going on in the second part of the code (besides a mess), anyway?
Admin
Spectrum Basic (and possibly other dialects) lacked an "else" construct. Maybe the author of the first sample is a dinosaur of the 1980es?
Is uses a little-known feature of the C preprocessor:
"one can put several strings one after another"
" like that"
" and the compiler will see a long one instead.";
Quite useful sometimes, if you know about it. Only this guy found a C toolchain that isn't fully ANSI C. IMO, the WTF is bothering to support a non-standard implementation at all.
Admin
Yeah, that first code falls under the "Unclear on the concept" category. Definitely weird.
The second part is used for when you've got a few different options for compilation but you have a file that's almost identical. For example, if you have code that runs on two chips, but the pins are in different locations. You may also find it used for "portability" so that a windows-specific directive is only called when it's possible to accept it.
It's also common practice in C and C++ to wrap all your .h files in
You do this because some compilers will try to include a file multiple times if you have #included it multiple times. You can end up with recursive compiles that take 30+ minutes to run. (This happened on a co-op job I did when I was in school. It was like that when I got there, and one time, the lead developer didn't even bother to compile before checking something in because it would have taken too long. Yes, it was wrong. Yes, I got blamed.)
Anyway, what it seems like he's doing is putting out a notice when you're compiling to let you know which compiler you're using. There could be a justification for that, but I'm not sure what it would be. Perhaps alcohol was involved. The problem is that they aren't using the printf() function correctly, and that's what the problem is. It works in the second case due to a compiler-specific implementation, but from what I can see, there's no way the first implementation would ever work. Thus, they never ran it with the GCC configuration. So that means that they don't have automatic configuration worked out to make the precompiler directives work (i.e. the #ifdef loops are useless) and they don't know how to do it manually.
It's late and I'm tired.
Admin
How the hell can someone not know how to use an ELSE?!?! I'm pretty sure I used VB elses on the first day I started programming.
Some people really shouldn't be programming, or allowed out of the house unattented for that matter.
Admin
WTF!
You mean the GCC allows the line ''printf("configuration: " CONFIG_STRING "\n");''?
Darryl
Admin
The real WTF in the second snippet would be if the comment was actually correct.
Admin
Yes Virginia, its called something like concatenation of literal strings.... (This only works for LITERAL strings!)
printf("HELLO " "CRUEL" "WORLD" "\n");
and
printf("HELLO CRUEL WORLD\n");
should be 100% identical... WHY? Well try writing this in assembly.... "HELLO" will be one variable/array.. "CRUEL" will be the next... What should go between "HELLO" and "CRUEL" in memory? Why should you call several routines to read/copy each portion instead of one routine for the entire length?
Other than a bit of extra work for the lexical parser, this feature in C/C++ actually simplifies things...
And in case you didn't catch it, CONFIG_STRING is probably a macro that evaluates to a literal string...
Admin
QBASIC had else blocks... I think... hmmm, now that I write that, I'm not sure. Anyone have better memory than I?
Admin
Most people would tend to just use commas between the args...
Admin
All compilers should. IIRC, Microsoft's got a #pragma once to change to nonstandard behavior, and GCC recognizes the #ifndef header guards. It also protects you from the multiple definitions you'd otherwise get if you include the same file twice. Recursive inclusion is far more rare.
BTW, identifiers containing a double underscore (or a leading underscore followed by a capital letter) are reserved. You should not use such names for your header guards. I tend to just use FILENAME_H_INCLUDED.
Admin
Or A includes B includes A loops.
Or it gives you multiple definition errors depending on what's in your headers.
As for the second example, I'm with the other posters in assuming that CONFIG_STRING is a preprocessor macro that expands to a string literal, in which case both cases should work. I don't particularily see it as a WTF even. I think it could have been done *nicer* with just a printf("configuration: %s\n", CONFIG_STRING) which as far as I can tell would have the same effect, wouldn't be really even the slightest bit confusing, and wouldn't have required an #ifdef, but in comparison with most of the code snippets on this site, it's pretty benign.
Admin
Admin
You know, the second one is why people work as a team, so you can ASK for advice, rather than leave behind confusing comments than end up on the Internet, bringing in amusement and laughter to our miserable lives.
Admin
I've seen a similar construct from a very experienced, but somewhat goto-happy C programmer:
Admin
I don't see what's so very bad about the second bit. The second form would suffice for any compiler obviating conditional compilation, and there are other ways it could be done, but if that's the worst of your conditional compilation, be very thankful!
I'm mostly impressed by the percentage of people who obviously know nothing about the intricacies of C but still feel compelled to post.
Admin
... except that that doesn't actually work in C. The code in the 'WTF' is probably correct, although it'll break if CONFIG_STRING has a % character in it. A simpler work-around would have been printf("stuff: %s\n", CONFIG_STRING), of course.
Admin
Yes. It's string literal concatenation and according to GCC is part of ANSI C. I'd link to an example in their documentation, but their online documentation doesn't appear to ever mention this, and as far as I can tell, the ANSI C specs aren't available online anyway.
But supposedly it's standard behavior. Stupid and dumb syntax, but standard behavior.
But in any case, printf() shouldn't be used if you're not using any of the formatting features. puts() exists for a reason.
Admin
They aren't. ISO and ANSI (& I think some random publisher) sell them. But believe the GCC standards; they're right. Here's the relevant section from the C++ standard:
(Section 2.13.4, paragraph 3; unchanged from the draft standard.)
Admin
It seems to me that in assembly, these are zero-terminated strings. That sure would make a difference...
blinkingtwelve
Admin
The compiler removes the zero before concatenating them. Putting "abcd" "efgh" in your code is the same as using "abcdefgh", possibly modulo undefined effects like it affecting the address of the resulting string or whether two strings that are both "abcdefgh" are represented in one or multiple memory locations. But if you, say, use it as an argument to printf, both will print the same on any conforming implementation.
Admin
By backwards, I was meaning the nature of VB to code in in general (which is probably why it's generally relegated to a prototyping language, as it's easy to write protos in but very backward in various types of syntax, functions and constructs, not to mention high system overhead and other factors that make it less useful as a longterm project language).
Admin
But supposedly it's standard behavior. Stupid and dumb syntax, but standard behavior.
Neither stupid or dumb, but quite useful. In the bad old days before ansi C one had no easy way to break up *long* literal string such that they were readable on display or paper. Printers tended to truncate after column 132 or so. Backslash newline combinations would always get lost in editing, causing cascading syntax errors at compile time.
With compile time string concatination long literals could be written so:
"The long string starts on this line "
"and continues on this line "
"and has even more text on this line, "
"etc."
Code that is easier to read is easier to debug, no? This makes long literals easier to read.
It's still a WTF, though. String concatenation should have never been used in that situation for about eleventy-seven reasons.
// marc
Admin
The first code snippet looks like VERY old school BASIC ( when it was spelled in uppercase, like COBOL ... ). In those ancient time, an if could only execute ONE instruction, and ( if my memories are right ) there was no 'else'. if you need several instructions, you need a gosub or a goto, indeed. This is what happen in machine code anyway, but programmers aren't machines, I guess ...
But the real reason is certainly near Dagon's guess. There are many embedded application specific WTF-languages around here. This 'programmer' was probably a script-kiddie with a convoluted mind due to mirc scripting, the worst language I've ever seen. In 98 there was no loops, no local variables, no arrays, quite limited conditionnal statements, non-reentrant functions ( no local variable means no stack, indeed ... unless you hack one yourself ). Any non-trivial structure needed a goto. The best thing is that the parser's behaviour changed at each version, forget about backward compatibility of scripts. It's certainly more complete now, but I would be surprised if it became any better and non-WTFesque. I know several mirc-kiddies that became 'real programmers', and as I've seen their 'progress', my guess is that this one is one of those ...
Admin
For the first one, it's he's fault for using VB.
The second one. this reminds be of atoi topic. Not all implementations conform to the standard. For all we know the compiler could be a custom made compiler built for the company.
Admin
Examples (Dartmouth (1964) and Locomotive (1984)):
10 IF X+Y>0 THEN 410
10 IF X+Y>0 THEN PRINT "FOO":A=0 ELSE GOTO 100
Admin
I find the fact that so many people are confused about the WTF here to be a WTF in itself. The code should read like this:
The basic problem is, what happens when you aren't using either GCC or the XYZ compiler? The preprocesor runs and the result is no code at all. All of the printf statements are completely eliminated. This is almost certainly not what was intended.
Admin
ISO/IEC JTC1/SC22/WG14 - C
See ISO/IEC 9899:1999 Working paper containing C99, TC1 and TC2 Section 6.4.5 "String literals". The "rationale for the C99 standard" contains some additional comments (section 6.4.5 as well). Some of these comments seem to be quite amusing:
Those members of the C89 Committee who insisted that string literals should be modifiable were content...
Do I see some sarcasm in between those lines? Anyway, there are some reasons why you would like to have them modifiable while there are other reasons why not. However would not matter that much, because programmers do not miss to write that const in front of char* p = "this is a string that will never be changed". Or do they? No way...Admin
Except that it's not legal. Identifiers that begin with a single underscore followed by a capital, or that contain a double underscore, or that begin with a capital E (as the errno constants) are reserved for the implementation (i.e. the system and standard header files). It doesn't matter that almost everyone does this. It's still not legal according to the C standard. An implementation, or a future version of the standard, could define __FILENAME to mean whatever it wants and break your code.
Admin
Dead-on. (though some situations would justify its use here. just not the use of printf)
In addition, you can indent the strings, where the backslash/newline combo leaves an un-indented mess. I still use the multiple string concatenation for the "Usage:" message for command line tools.
puts("Usage: progname [options] arg0 arg1 arg2\n"
"Where:\n"
"\t-a = blah blah\n"
"\t-b = blah blah\n"
"\t-n = blah blah blah\n"
"\targ0..2 = the name of the file to blah blah\n"
);
The above line results in a large string constant written out in a single series of bytes in the program's data segment.
In Java, you would put a "+" between each of the strings. This technically translates to a series of "append" method calls on an implicit StringBuffer. Its up to your compiler to realize that the append operations are all performed on constant data, and that the whole of it can be replaced with a large string constant.
Back in earlier C days, you definately wouldn't want to be relying on the optimizations of your compiler to prevent a bunch of runtime string concatenation. (not that C had that ability anyway)
Admin
I probably ruined a whole bunch of people's fun watching so many forum participants stumble all over themselves saying all kinds of ridiculous things about the second code snippet. It's really sad when most of the WTF forum posters are no better than those who provide the main fodder for the articles.
Admin
Admin
The modern C++ equivalent is adding together a series of ::std::string objects, which is generally handled less efficiently than Java's string concatenation of constant strings at compile time.
Of course, the preprocessor string concatenation thing in no way relies on the compiler for its efficiency or to work at all. It is all done by the preprocessor before the compiler sees any of it. All the compiler itself ever sees is the string as one big chunk.
Java doesn't have a preprocessor, so there is no place really where automatic concatenation of adjacent constant strings can happen. (Though it is a fairly simple syntax rule, and you could just define a string constant to allow arbitrary whitespace between quoted sections.) So the '
+
' operator is used and the compiler is relied upon to make this efficient.Admin
In my first job, I worked for a company that did all their work in Pascal. I found a rather weird pattern repeated everywhere, and upon asking, was told that these were written by the owner of the company (back when he still wrote code). Since the man is a reputed genius, obviously there cannot be nothing wrong with it...The pattern is as follows (translated to C++ because I cannot remember Pascal syntax now...):
Notice anything slightly unusual?
Admin
Oh! Oops, you're right. *sheepish grin*
You could use
fputs
andputs
in the second case, but I think that would be kind of obscure for little benefit. Additionally, the#else
section has the nice benefit of explaining the#if
section for people who don't know about ANSI preprocessor string concatenation, which is apparently quite a few people.Admin
(irrelevant code removed):"
Apparently, someone isn't familiar with the concept of an "Else" block."
---------------
Maybe some relevant code was removed after all. If this is code snippet was found in a WHILE loop, the 'Goto skipIt' may well have been there due to the lack of a 'continue' statement in VB.
Admin
Well, I found it stupid to optimize a fragment of code that is supposedly run only once. What is the gain of using compiler-specific puts("A" "B") instead of printf("A %s\n","B"); when it's called only to show configuration?
And probably he didn't use #else for some reason (maybe other compilers do not bother to define CONFIG_STRING at all).
And yes, string concatenation is quite usefull for long strings spanning across several lines.
And yes, using unknown string for a format is illegal in several countries, although I wouldn't expect the compiler to perform buffer overruns to hack it's own code.
Admin
Admin
#import is also a valid keyword in dev-cpp, so it's probably valid in every g++-like compiler
Admin
Why?
Wouldn't this do:
Admin
You're right about that :-). I think my boggle-o-meter exploded when someone suggested that printf will produce output while compiling.
And what is the deal with so many people not knowing about literal string concatenation? I don't know, kids today, etc.
(btw, aside from readability, string concatenation is very useful when trying to embed \x sequences into string literals.)
Admin
Ooh! Let me. Business Basic, the language of the ages, has been evolving for years. (Go ahead. I'll wait.) So when I started my current job, I was reviewing the code that went before me to sort of learn the lay of the land. I came across this little gem:
0220 IF K$(9,1)<>"Y" THEN LET Q$=K$(10,3),A=NUM("A",ERR=0310)
Now, for those not familiar, the highly favored "GOTO" statement did not exist in early versions of Business Basic, so programmers found all kinds of interesting ways to get around that shortcoming. Nevermind that all variables are global....
Yes, the language still exists, but it's java-based (believe it). We dumped it for VB several years back, but must still support 'way too many folks for a while yet. Until I quit. I can't wait.
Admin
That would be 3 function calls instead of a single... The WTF in combination with what Omnifarious is saying is that there are C compilers not supporting this kind of concatenation. Even in my 7-year of embedded C development and a lot of obscure C compilers, I never encountered one which doesn't support this basic feature... Anyone any idea about which compiler was used? :)
Admin
I once met a programmer that was writing some of those "if goto next". It took me one whole hour to get him to understand that his:
Was exactly equivalent to the much simpler:
The last time I heard about the guy, he was working at an ISP helpdesk...
Admin
This construct is not all that uncommon. But "first" needs to be defined as a non-stack based variable (static, etc) or it will be initialized to true every time.
Admin
Any standard implementation of printf should produce the desired result without the need to call printf thrice regardless of concatenation support:
printf("configuration: %s\n",CONFIG_STRING);
Admin
This is pedantic, I know, I'm sorry, but I can't put up with the compiler versus pre-processor being mixed-up for any longer...
The C-preprocessor does not do any string concatenation.
Any concatenation that occurs is the compiler not the preprocessor.
Admin
THANKS GODS C IS NOT DELPHI:
if ( whatever) then
begin
foo();
end;
THANKS GODS IS NOT BASIC:
if ( condition ) foo();
or
if (condition) {
foo();
}
Admin
That's definitely the best approach so far. The only reason to jump through any fancy preprocessor hoops would be if there were a large performance gain to be had. This looks to be just writing diagnostic output, likely low volume.
The real issue here is a pretty common one -- developers' fear of changing anything that they didn't write themselves. It's common and usually baseless. Step up, take ownership, and make it better!
Admin
Forget not perl:
if (condition) foo();
foo() if (condition);
(condition) && foo();
unless (!condition) foo();
foo() || die;
captcha = paste, it's good for your teeth, makes them perly white.