worst.c - foolishness

A

Arthur J. O'Dwyer

ITYM
char* fmt = "%d, %l", c;

My mistake. ;-)
It would be better though if c was somehow used as if it were a
char* instead. Otherwise it just adds up to obfuscation.

I think you'd have trouble avoiding a compiler warning in that case.
Dunno, it's one bug less if you ignore the misdefinition..

How so? My change merely replaces "undefined behavior upon calling
unprototyped function with wrong arguments" (which Chuck already had
elsewhere) with "undefined behavior upon passing NULL to feof()". Plus,
my bug is much subtler.

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.

Doesn't that remove the bug, though? scanf("%d%s", z, &c) will
most likely try to store a string in the memory pointed to by &c
(invoking undefined behavior on buffer overrun); but the bug I was
trying to introduce there was that

scanf("%d", &foo);
gets(bar);

will store a number in 'foo', and then, assuming the user has pressed
'Return' to end that line of input, will proceed to read and discard
a single newline. OTOH, the gets() doesn't actually have a bug then;
it will store only a single '\0', won't it? So maybe keep that gets(),
but introduce the

scanf("%d", &foo);
fgets(&c, sizeof &c, stdin);

bug(s) elsewhere in the code. [Bugs include lack of prototype for
fgets, causing undefined behavior when passing literal 0 as third
argument; mis#defined 'stdin' that causes the literal 0 in the first
place; passing NULL to fgets in the first place; buffer overflow;
abuse of the 'sizeof' operator; lack of error-checking on scanf;
and the above-mentioned mishandling of possible newline characters
in the input.]

#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) {

I think the use of == for != is too blatant a mistake. But it
occurs to me that we haven't misused De Morgan's Rule yet; we need
something along the lines of

while (feof()!=EOF || c=(int)getchar() != EOF) {

[I like my cast better than yours. Yours is only designed to
placate the compiler, AFAICT; mine has the "good" intention of
making sure the result of getchar() is wide enough to hold 'EOF'
before assignment to c. ;-) ]
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);
}

Finally, it occurs to me that we haven't abused 'goto' yet, nor
attempted to 'switch' on some inappropriate type. Nor even inserted
anywhere an

if (strfmt == "foo")

;-)
-Arthur
[Disclaimer: THIS WHOLE THREAD IS A JOKE. THIS IS INTENTIONALLY
BAD CODE. WE KNOW IT DOES NOT WORK. :) ]
 
C

CBFalconer

Nils said:
. snip ...

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 */\

My original criterion was that "gcc worst.c" accepts and links
without any protest.
 
J

Jack Klein

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.

I never use a compiler that does not have issue warnings for calls to
unprototyped functions. And I never use such a compiler without the
option demanding that it do so.

The last compiler around that cannot be forced to do so dates from
1995, and is still used some in maintaining a legacy product.
 
J

Jarno A Wuolijoki

My mistake. ;-)


I think you'd have trouble avoiding a compiler warning in that case.

Not really. Strings are usually handled through functions and we're
not including the important stuff to get complaints. (though in this
respect gcc is sometimes one of the "smart compilers" with its built in
checking for variadic functions)

How so? My change merely replaces "undefined behavior upon calling
unprototyped function with wrong arguments" (which Chuck already had
elsewhere) with "undefined behavior upon passing NULL to feof()". Plus,
my bug is much subtler.

Ok. Just that the bug's on another line, here we just see the results;)

Doesn't that remove the bug, though? scanf("%d%s", z, &c) will
most likely try to store a string in the memory pointed to by &c
(invoking undefined behavior on buffer overrun); but the bug I was
trying to introduce there was that

scanf("%d", &foo);
gets(bar);

will store a number in 'foo', and then, assuming the user has pressed
'Return' to end that line of input, will proceed to read and discard
a single newline.

Ouch. I completely unrealized the intent there..

OTOH, the gets() doesn't actually have a bug then;
it will store only a single '\0', won't it? So maybe keep that gets(),
but introduce the

scanf("%d", &foo);
fgets(&c, sizeof &c, stdin);

bug(s) elsewhere in the code. [Bugs include lack of prototype for
fgets, causing undefined behavior when passing literal 0 as third
argument; mis#defined 'stdin' that causes the literal 0 in the first
place; passing NULL to fgets in the first place; buffer overflow;
abuse of the 'sizeof' operator; lack of error-checking on scanf;
and the above-mentioned mishandling of possible newline characters
in the input.]

You're approaching the bubble sort:

sizeof abuse, off by 2 error had it worked, unsigned gotcha,
z vs zz, extra ;, dangerous comparision, sequence point problem on
swap, zeroing data when &__a==&__b, invasion of implementation
namespace, possible trap when performing binary stuff on chars
and modification of a string literal.

I think the use of == for != is too blatant a mistake. But it
occurs to me that we haven't misused De Morgan's Rule yet; we need
something along the lines of

Nah. It just shows why you shouldn't write bad code in the first place.
Mistakes invite more mistakes. It was a genuine;)

while (feof()!=EOF || c=(int)getchar() != EOF) {

Subtle.. I don't like the doublecheck for eof though. Checking first
for eof and then for errors makes it look better thought out.

[I like my cast better than yours. Yours is only designed to
placate the compiler, AFAICT; mine has the "good" intention of
making sure the result of getchar() is wide enough to hold 'EOF'
before assignment to c. ;-) ]

So it's
"hideous practice that lets you shoot your own foot quietly"
against
"terrible misunderstanding of how the language works" ;)

Finally, it occurs to me that we haven't abused 'goto' yet, nor
attempted to 'switch' on some inappropriate type. Nor even inserted
anywhere an
if (strfmt == "foo")
;-)

I like !strcmp(strfmt, "foo")==0 too (for having actually seen it), but
maybe it's too obvious..
 
C

CBFalconer

Dan said:
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:

Hey look - I made up this game, so we'll play by MY rules :) If
you don't do so I'll take my ball away and go home. ;-[
 
C

CBFalconer

Jack said:
.... snip ...

I never use a compiler that does not have issue warnings for calls to
unprototyped functions. And I never use such a compiler without the
option demanding that it do so.

In reality I had to go around my normal aliases to avoid using
reasonable flags. But with them I wouldn't have been able to
easily create worst.c :)

My normal configuration results in:
c:\c\junk>gcc worst.c
worst.c:16: warning: return type defaults to `int'
worst.c: In function `main':
worst.c:19: warning: initialization discards qualifiers from
pointer target type
worst.c:22: warning: implicit declaration of function `feof'
worst.c:23: warning: implicit declaration of function `getchar'
worst.c:26: warning: implicit declaration of function `gets'
worst.c:27: warning: implicit declaration of function `printf'
worst.c:28: warning: implicit declaration of function `fflush'
worst.c:29: warning: implicit declaration of function `malloc'
worst.c:30: warning: implicit declaration of function `realloc'
worst.c:32: warning: comparison of unsigned expression >= 0 is
always true
worst.c:17: warning: `x' might be used uninitialized in this
function

No fun at all :-[
 
N

Nils Petter Vaskinn

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.

We should have (apparently) nested loops then?
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?

It's the result of a bug in my internal typing routines.
 
A

August Derleth

CBFalconer said:
Dan said:
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:


Hey look - I made up this game, so we'll play by MY rules :) If
you don't do so I'll take my ball away and go home. ;-]

Pop's got a point, as usual. :)

If you don't pass any arguments to gcc, it compiles a C-like language
called GNU C. If you pass the correct arguments, it compiles Standard C.
As this is clc, we want to discuss Standard C as opposed to GNU C.

You could take your ball to a gcc-specific froup and play it by your
rules there, but it really isn't on-topic here due to some oddnesses of
how gcc behaves by default.

For example:

int foo(int arg)
{
int bar(int gry)
{
int zee = 23;

return gry * zee;
}

return bar(arg);
}

is a perfectly correct GNU C program, and it behaves such that bar() is
only visible within foo(). bar() is a local function, something that
does not exist in Standard C. I have no idea why the gcc people decided
to do that, but so far the Standards committee hasn't seen fit to
canonize the behavior. ;)
 
C

CBFalconer

August said:
CBFalconer said:
.... snip ...

Hey look - I made up this game, so we'll play by MY rules :) If
you don't do so I'll take my ball away and go home. ;-]

Pop's got a point, as usual. :)

If you don't pass any arguments to gcc, it compiles a C-like language
called GNU C. If you pass the correct arguments, it compiles Standard
C. As this is clc, we want to discuss Standard C as opposed to GNU C.

You could take your ball to a gcc-specific froup and play it by your
rules there, but it really isn't on-topic here due to some oddnesses
of how gcc behaves by default.

Yabbut. Default gcc still compiles standard C, it just doesn't
criticize as much. If I had specified "no warnings on any
compiler with any settings" the task would be virtually
impossible. So for this game I consider Pops point ponderously
pedantic for the populace. :)
 
D

Dan Pop

In said:
Yabbut. Default gcc still compiles standard C,

Let's see:

fangorn:~/tmp 15> cat test.c
int main()
{
int asm = 0;
return asm;
}

Looks like a standard C program to me, unless I'm missing something...

fangorn:~/tmp 16> gcc test.c
test.c: In function `main':
test.c:3: parse error before `asm'
fangorn:~/tmp 17> gcc -ansi test.c
fangorn:~/tmp 18>
it just doesn't
criticize as much. If I had specified "no warnings on any
compiler with any settings" the task would be virtually
impossible. So for this game I consider Pops point ponderously
pedantic for the populace. :)

As usual, you're in dire need of a clue. If you want gcc to compile
correct standard C code as such, you NEED -ansi, period. If you want
gcc to behave as a conforming standard C compiler, you need -pedantic,
too, otherwise you won't get certain *mandatory* diagnostics.

One doesn't have to be a genius to realise that a game that doesn't
involve a conforming C compiler is pointless in the context of this
newsgroup.

Dan
 
J

Jeremy Yallop

CBFalconer said:
August said:
CBFalconer said:
... snip ...

Hey look - I made up this game, so we'll play by MY rules :) If
you don't do so I'll take my ball away and go home. ;-]

Pop's got a point, as usual. :)

If you don't pass any arguments to gcc, it compiles a C-like language
called GNU C. If you pass the correct arguments, it compiles Standard
C. As this is clc, we want to discuss Standard C as opposed to GNU C.

You could take your ball to a gcc-specific froup and play it by your
rules there, but it really isn't on-topic here due to some oddnesses
of how gcc behaves by default.

Yabbut. Default gcc still compiles standard C, it just doesn't
criticize as much.

Nope. Unless you specify -ansi it compiles GNU C. For instance, it
won't compile the following:

/* `asm' and `typeof' are keywords in GNU C */

int main(int asm, char **typeof) { return 0; }

and the following has different behaviour:

int main() { return 2 //* GNU C has end-of-line comments */ 1
; }

Jeremy.
 
J

Jirka Klaue

Jeremy Yallop wrote:
....
and the following has different behaviour:

int main() { return 2 //* GNU C has end-of-line comments */ 1
; }

It returns 2 in one case and, in contrast, returns 2 in the other case?

Jirka
 
C

CBFalconer

Dan said:
Let's see:

fangorn:~/tmp 15> cat test.c
int main()
{
int asm = 0;
return asm;
}

Looks like a standard C program to me, unless I'm missing something...

fangorn:~/tmp 16> gcc test.c
test.c: In function `main':
test.c:3: parse error before `asm'
fangorn:~/tmp 17> gcc -ansi test.c
fangorn:~/tmp 18>


As usual, you're in dire need of a clue. If you want gcc to compile
correct standard C code as such, you NEED -ansi, period. If you want
gcc to behave as a conforming standard C compiler, you need -pedantic,
too, otherwise you won't get certain *mandatory* diagnostics.

One doesn't have to be a genius to realise that a game that doesn't
involve a conforming C compiler is pointless in the context of this
newsgroup.

This time you are completely right about gcc vs standard C.
Thanks for pointing it out in your normal diplomatic manner.
 

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

Forum statistics

Threads
474,135
Messages
2,570,784
Members
47,342
Latest member
KelseyK737

Latest Threads

Top