worst.c - foolishness

C

CBFalconer

Presented without further comment for "improvement"

/* ---------- worst.c -----------*/

/* The objective here is to include as many C errors as
possible, without triggering the compiler into objecting.
I have tried to get an error into each line. Logical
foulups count. The test compiler is gcc 3.2.1, executed
with "gcc worst.c", i.e. with absolutely no extra warning
enabled, and linking successfully.
I have tried for at least one error per line. However
some variable declarations remain completely valid */

#define EOF -1
#define stdin 0

main()
{
int x, y;
char c;
char *fmt = "%d, %l";
unsigned int z;

while (!feof()) {
c = getchar();
if (EOF == c) continue;
}
gets(&c);
printf(fmt, &c, x);
fflush(stdin);
fmt = (char *)malloc(123);
fmt = (char *)realloc(fmt, 245);
y = fmt[1000];
for (z = 10; z >=0; z--) x += z;
if (z > 0) return -1;
} /* worst main */
 
J

Jarno A Wuolijoki

Presented without further comment for "improvement"

/* ---------- worst.c -----------*/

/* The objective here is to include as many C errors as
possible, without triggering the compiler into objecting.
I have tried to get an error into each line. Logical
foulups count. The test compiler is gcc 3.2.1, executed
with "gcc worst.c", i.e. with absolutely no extra warning
enabled, and linking successfully.
I have tried for at least one error per line. However
some variable declarations remain completely valid */

#define EOF -1
#define stdin 0

main()

You define main like this yet it's not recursive?

{
int x, y;
char c;
char *fmt = "%d, %l";

Just fmt? What's the type of fmt?

unsigned int z;

while (!feof()) {

While what? Always prefer an explicit comparision.

c = getchar();

Casting this one makes a better impression.

if (EOF == c) continue;
}
gets(&c);
printf(fmt, &c, x);
fflush(stdin);
fmt = (char *)malloc(123);
fmt = (char *)realloc(fmt, 245);
y = fmt[1000];
for (z = 10; z >=0; z--) x += z;

I'd try something that involves swapping..
 
A

Arthur J. O'Dwyer

Presented without further comment for "improvement"

Added comments inline; re-copied the new and "improved" version
at the bottom of this post.
/* ---------- worst.c -----------*/

/* The objective here is to include as many C errors as
possible, without triggering the compiler into objecting.
I have tried to get an error into each line. Logical
foulups count. The test compiler is gcc 3.2.1, executed
with "gcc worst.c", i.e. with absolutely no extra warning
enabled, and linking successfully.
I have tried for at least one error per line. However
some variable declarations remain completely valid */

#define EOF -1
#define stdin 0

main()
{
int x, y;
char c;
char *fmt = "%d, %l";

These two lines should probably be combined. Note the subtle change
in the indentation, also.

char *fmt = "%d, %l", c;
unsigned int z;

while (!feof()) {

Surely you meant

while (!feof(stdin)) {

This will avoid the warnings from those so-called "smarter" compilers. :)
c = getchar();

I agree with Jarno; haven't you learned about the return type of
getchar() yet? This line should, of course, read

c = (int)getchar();
if (EOF == c) continue;
}

You're missing a

scanf("%d", z);

here.
gets(&c);
printf(fmt, &c, x);
fflush(stdin);
fmt = (char *)malloc(123);
fmt = (char *)realloc(fmt, 245);

Why are you *assigning* the result of the 'realloc' call here?
Wouldn't it suffice to write

(void)realloc(&fmt, 245);

This also avoids that nasty memory leak.
y = fmt[1000];
for (z = 10; z >=0; z--) x += z;
if (z > 0) return -1;
} /* worst main */


== worst.c Revised Version ==

/* ---------- worst.c -----------*/

/* The objective here is to include as many C errors as
possible, without triggering the compiler into objecting.
I have tried to get an error into each line. Logical
foulups count. The test compiler is gcc 3.2.1, executed
with "gcc worst.c", i.e. with absolutely no extra warning
enabled, and linking successfully.
I have tried for at least one error per line. However
some variable declarations remain completely valid */

/* Extra evilness, plus bonus bug, added by AJO. My gcc
complains about the use of 'gets', though */

#define EOF -1
#define stdin 0

main()
{
int x, y;
char *fmt = "%d, %l", c;
unsigned int z;

while (!feof(stdin)) {
c = (int)getchar();
if (EOF == c) continue;
}

scanf("%d", z);
gets(&c);
printf(fmt, &c, x);
fflush(stdin);

fmt = (char *)malloc(123);
(void)realloc(&fmt, 245);
y = fmt[1000];

for (z = 10; z >=0; z--) /* Add up some positive numbers
x += z; from 0 to 10 */

printf("%ul", (unsigned long)z);

if (z > 0) return -1;
} /* worst main */


-Arthur
[Disclaimer: ALL OF THE ABOVE IS A JOKE. IT IS EVIL AND WRONG
AND BAD, AND MUST NOT BE TAKEN SERIOUSLY.]
 
J

Jack Klein

You define main like this yet it's not recursive?

Of course it is recursive. main() always is in C.
Just fmt? What's the type of fmt?

Pointer to char. How did you miss that?
While what? Always prefer an explicit comparision.

This is an explicit comparison. It is an explicit comparison of the
int value returned by feof() with 0, the result then negated.
c = getchar();

Casting this one makes a better impression.

if (EOF == c) continue;
}
gets(&c);
printf(fmt, &c, x);
fflush(stdin);
fmt = (char *)malloc(123);
fmt = (char *)realloc(fmt, 245);
y = fmt[1000];
for (z = 10; z >=0; z--) x += z;

I'd try something that involves swapping..

if (z > 0) return -1;
} /* worst main */
 
J

Jack Klein

Of course it is recursive. main() always is in C.


Pointer to char. How did you miss that?


This is an explicit comparison. It is an explicit comparison of the
int value returned by feof() with 0, the result then negated.

....that is, assuming it returns a value since it invokes undefined
behavior by omitting the required FILE * argument.

c = getchar();

Casting this one makes a better impression.

if (EOF == c) continue;
}
gets(&c);
printf(fmt, &c, x);
fflush(stdin);
fmt = (char *)malloc(123);
fmt = (char *)realloc(fmt, 245);
y = fmt[1000];
for (z = 10; z >=0; z--) x += z;

I'd try something that involves swapping..

if (z > 0) return -1;
} /* worst main */


--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++ http://www.contrib.andrew.cmu.edu/~ajo/docs/FAQ-acllc.html
 
A

Arthur J. O'Dwyer

This is an explicit comparison. It is an explicit comparison of the
int value returned by feof() with 0, the result then negated.

I do believe all of Jarno's questions were rhetorical, albeit
not very well-formed (English not being his first language). Obviously,
to conform to Chuck's "improvement" metric, main() should call itself,
something should be done about the type of fmt, and the above line
should be re-written

while (feof() != TRUE) {

for some suitable value of TRUE, to provide the "explicit comparison."
(Yes, that introduces an additional bug to the three already present
in that line. That's the point.)

;-)
-Arthur,
explaining a joke always makes it funnier
 
M

Martin Ambuhl

Jarno said:
You define main like this yet it's not recursive?

Of course it's recursive. What obscure point are you trying to make?
Just fmt? What's the type of fmt?

It sure looks like it's a pointer to char ("char *"), doesn't it? What
obscure point are you trying to make?

While what? Always prefer an explicit comparision.

Why? That would neither add or detract from CBF's avowed intent of writing
truly awful code that could slip past a compiler, although he is using his
with warnings almost disabled. Your advice sucks, but if you can't read
straight-forward C, by all means engage in typing practice.
 
N

Nils Petter Vaskinn

Added comments inline; re-copied the new and "improved" version
at the bottom of this post.


for (z = 10; z >=0; z--) /* Add up some positive numbers
x += z; from 0 to 10 */

You missed a semicolon. All lines should have a terminating semicolon,
right? So that should be:

for (z = 10; z >=0; z--); /* Adds up some positive numbers
x += z; from 0 to 10 */

-Arthur
[Disclaimer: ALL OF THE ABOVE IS A JOKE. IT IS EVIL AND WRONG
AND BAD, AND MUST NOT BE TAKEN SERIOUSLY.]
 
C

CBFalconer

Jack said:
...that is, assuming it returns a value since it invokes undefined
behavior by omitting the required FILE * argument.

You forget the objective is to make errors without having the
compiler complain. With no #include and no feof() prototype there
is no required argument and no complaint.

I specified the compiler and commands to use. I couldn't use void
main without triggering something elsewhere. There is actually
some value to this, because it alerts you to the sort of thing
that you won't get warnings for.
 
M

Mark A. Odell

You missed a semicolon. All lines should have a terminating semicolon,
right? So that should be:

for (z = 10; z >=0; z--); /* Adds up some positive numbers
x += z; from 0 to 10 */\

You're joking right? the semi-colon makes the for loop stand apart from
the statement x += z;

for (x = 0; x < 10; x++)
y = 0;

is a (IMHO) sloppy short-hand for

for (x = 0; x < 10; x++)
{
y = 0;
}
 
J

Jarno A Wuolijoki

Of course it's recursive. What obscure point are you trying to make?

It doesn't explicitly call itself. This is a grand win since you are
empowered to pass it whatever arguments you wish.

It sure looks like it's a pointer to char ("char *"), doesn't it? What
obscure point are you trying to make?

Ah, sorry. Sure it's type is pointer to char, but I was really after
the kind of content it's trying to represent. Your confusion here shows
precisely why hungarian notation is so important.
Moreover, since the format may be used in other parts of the program
I'd suggest making it a global.

Why? That would neither add or detract from CBF's avowed intent of writing
truly awful code that could slip past a compiler, although he is using his
with warnings almost disabled.

How do you know what value feof returns at the end? The code doesn't
spell it out loud. See?

Your advice sucks, but if you can't read
straight-forward C, by all means engage in typing practice.

Great advice, I've heard that RBTL is overrated these days anyway.
 
N

Nils Petter Vaskinn

Did you miss the part where this code is INTENTIONALLY bad?

Well at least he spotted the error when he thought it was serious. But the
other equally sinister error which he missed (as did I at first) is the
failure to close the comment (it'll stand out in a syntax highlighting
editor, but gcc remains quiet).

Since logical errors count too I guess we could improve thee code more by
changing it to:

for (z = 10; z > 1; z--); /* Adds up some positive numbers
x += z; from 1 to 10 */\
 
A

Arthur J. O'Dwyer

[Arthur wrote:]
for (z = 10; z >=0; z--) /* Add up some positive numbers
x += z; from 0 to 10 */

You missed a semicolon. All lines should have a terminating semicolon,
right? So that should be:

for (z = 10; z >=0; z--); /* Adds up some positive numbers
x += z; from 0 to 10 */\

You're joking right?

Did you miss the part where this code is INTENTIONALLY bad?

Well at least he spotted the error when he thought it was serious. But the
other equally sinister error which he missed (as did I at first)

MUHAHAHAHA! MUHAHAHAHA! MUHAHA... well, anyway...
That's one of my favorite intentionally-bad bugs, even though
I've never actually seen it anywhere except intentionally obfuscated
code.
is the
failure to close the comment (it'll stand out in a syntax highlighting
editor, but gcc remains quiet).

Since logical errors count too I guess we could improve thee code more by
changing it to:

ITYM "improve /thy/ code more..." ;-)
for (z = 10; z > 1; z--); /* Adds up some positive numbers
x += z; from 1 to 10 */\

This change removes one of the bugs that was already present -- the
infinite loop on the value of z (which by definition is always >= 0).
Of course, my changes removed the infinite loop, too, by returning
from main inside the loop -- but still I think the comparison of an
unsigned value against 0 is a big enough bug that it should remain
intact.
Oh, and what's the deal with the extra backslash at the end of the
line? Is that a newsreader artifact, or a potential bug I'm just not
seeing?

-Arthur
 
J

Jarno A Wuolijoki

These two lines should probably be combined. Note the subtle change
in the indentation, also.
char *fmt = "%d, %l", c;

ITYM
char* fmt = "%d, %l", c;
It would be better though if c was somehow used as if it were a char* instead.
Otherwise it just adds up to obfuscation.

Surely you meant
while (!feof(stdin)) {
This will avoid the warnings from those so-called "smarter" compilers. :)

Dunno, it's one bug less if you ignore the misdefinition..

I agree with Jarno; haven't you learned about the return type of
getchar() yet? This line should, of course, read
c = (int)getchar();

I was after char, to shut up those "smarter" compilers that warn about
lossy conversions. Apparently gcc isn't one of them though.

You're missing a
scanf("%d", z);
here.

My linker warns about gets so I'd fuse these two into one scanf. You
can use c as if it was a pointer there too.

printf(fmt, &c, x);
fflush(stdin);
fmt = (char *)malloc(123);
fmt = (char *)realloc(fmt, 245);

Why are you *assigning* the result of the 'realloc' call here?
Wouldn't it suffice to write

(void)realloc(&fmt, 245);

This also avoids that nasty memory leak.
y = fmt[1000];
for (z = 10; z >=0; z--) x += z;

for (z = sizeof fmt; z>=0; z--) for (zz = z; z>=0; zz--);
if (fmt[z]-fmt[zz]<=0) fmt[z] ^= fmt[zz] ^= fmt[z] ^= fmt[zz];

...before mallocation of course, to sort the string constant.


#define EOF -1
#define stdin 0
#define swap(__a, __b) (__a ^= __b ^= __a ^= __b)

char* strfmt = "%d, %l", strtmp;

main()
{
int x, y;
char c;
unsigned z, zz;

while (feof()==EOF) {
c = (char) getchar();
if (c<0) continue;
}
scanf("%d%s", z, strtmp);
printf(strfmt, strtmp, x);
fflush(stdin);
for (z = sizeof strfmt; z>=0; z--) for (zz = z; z>=0; zz--);
if (strfmt[z]-strfmt[zz] <= 0) swap(strfmt[z], strfmt[zz]);
strfmt = (char*) malloc(123);
(void) realloc(&strfmt, 245);
y = strfmt[1000];
if (z>0) return -1;
else return main(42.7f);
}
 
L

Larry Doolittle

Jarno said:
#define swap(__a, __b) (__a ^= __b ^= __a ^= __b)

Given its lack of protective parentheses, and multiple uses
of each argument, this just cries out for buggy usage later:

swap(strfmt[z++], c+d);

Needs some work to avoid syntax errors (e.g., invalid lvalue in
assignment), but this is a category of errors that is otherwise
untapped by this example.

- Larry
 
J

Jan Engelhardt

#define swap(__a, __b) (__a ^= __b ^= __a ^= __b)
Given its lack of protective parentheses, and multiple uses
of each argument, this just cries out for buggy usage later:

swap(strfmt[z++], c+d);

Needs some work to avoid syntax errors (e.g., invalid lvalue in
assignment), but this is a category of errors that is otherwise
untapped by this example.

Earlier in this newsgroup (many months away), it was said that
compilers may optimize things like

int tmp;
tmp = b;
b = a;
a = tmp;

away (i.e. to XCHG instruction), however they might not actually do so
with a ^= b ^= a ^= b; but replace it with a fistload of XOR operations.
 
D

Dan Pop

In said:
Presented without further comment for "improvement"

/* ---------- worst.c -----------*/

/* The objective here is to include as many C errors as
possible, without triggering the compiler into objecting.
I have tried to get an error into each line. Logical
foulups count. The test compiler is gcc 3.2.1, executed
with "gcc worst.c", i.e. with absolutely no extra warning
enabled, and linking successfully.

Wrong compilation command. You're asking gcc to treat worst.c as a
GNU C program, NOT as a C program. You really need -ansi -pedantic
if you want to be sure that your code doesn't contain errors that a
C compiler MUST diagnose. Trivial example:

fangorn:~/tmp 69> cat test.c
main() { return sizeof(void); }
fangorn:~/tmp 70> gcc test.c
fangorn:~/tmp 71> gcc -ansi -pedantic test.c
test.c: In function `main':
test.c:1: warning: sizeof applied to a void type

Dan
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,808
Messages
2,569,684
Members
45,435
Latest member
HemanttSod

Latest Threads

Top