Comparision of C Sharp and C performance

B

Ben Bacarisse

spinoza1111 said:
Yes, this code is buggy. If there is a nonzero value at *str and ferror
(fp) returns true it will loop.

However, this is as much the "fault", if "fault" there be, in McGraw
Hill's technical editors, since it's long been known that bug-free
software can only be obtained with group reviews (group reviews free
of the insane back-stabbing one sees here).

The book appears to have been published in several edition over a
period of 13 years (I can find ISBNs for editions or reprints in 1987,
1988, 1990, 1995 and 2000). If I were the author I would want to
correct as many errors as possible at some point in the 13 year
process.

With technical books, I don't think the publisher can be expected have
editors that know C better than the author of their C books.
Instead of his stupid and shameful vendetta against Schildt as a
person, Seebach should have accepted McGraw Hill's offer of a small
amount of money to tech review the book like a true professional.

That is such an odd remark. I have been asked on several occasions to
do technical reviews of books and articles. Some I've done, but i
don't feel any responsibility for errors in the books and articles
that I declined to review.

<snip>
 
R

Richard Bos

Nick Keighley said:
it basically meant the user was doing the lexical analysis! As I
understood it if you typed "IF" (I assuming IF is a valid keyword in
Spectrum Basic) the the interpreter didn't understand you but if you
typed shift-bucky-I (the I key having the word "IF" on it as well)
then an "IF" was added to the program. The interpreter had its key
words pre-tokenised for it!

You understand wrong. If you were at a point where the command entry
routine wanted a keyword, you _could_ not type "IF". You pressed the 'U'
key, and that would result, without any shift keys being needed, in the
'IF' keyword being entered. If you typed 'I' 'F' instead, you'd get
'INPUT' 'F'.
As a side note, you could, and would, use symbol shift, but only to
enter other grammatical parts of commands such as '<' or 'THEN' (and,
anomalously, the 'STOP' keyword). You'd also use it combined with caps
shift to enter "extended mode", in which you could enter less common
keywords such as 'BEEP' or 'ABS'.

In the end, though, it was a pure interpreter, but what you entered was
whole keywords, not text. It was possible, by trickery, to get it to see
the text "IF" rather than the keyword 'IF' where it expected a keyword,
but it wouldn't accept the line if you did so.

Richard
 
R

Richard Bos

Beej Jorgensen said:
Beej's compliant PRNG implementation?

int rand(void)
{
return 3490;
}

I think that's on the borderline between compliant and non-comp, and IMO
tripping over it. The Standard sayeth:

# The rand function computes a sequence of pseudo-random integers in the
# range 0 to RAND_MAX.

One could quibble about whether the single number 3490 is a sequence of
integers in the range 0 to RAND_MAX. I'd quibble that it isn't, within
the meaning of the act, m'lud. I would expect both 0 and RAND_MAX to be
included, with RAND_MAX being at least 32767. Since srand() also needs
to work (although it does not need to start _different_ sequences for
its seeds), I would suggest that the minimum awful-yet-compliant rand()
function set is:

#define RAND_MAX 32767
static int __rand=0;

int rand(void)
{
return __rand^=RAND_MAX;
}
void srand(unsigned int seed)
{
__rand=0;
}

By the way, it was IMAO an error to make srand() take an unsigned int,
when rand() returns a signed one.

Richard
 
B

Beej Jorgensen

The problem is with the 'pseudo-random'. It fails to specify what
tests the generated sequence must pass in order to be accepted.

Indeed, the standard doesn't even take a stab at the definition of
"pseudo-random". I think it's probably happy to let the free market
sort that one out. :) "So, your PRNG just outputs the number 3490 over
and over... that's crap, see."
What about the following definition:

int rand(void){
static int i = 0;
++i;
return abs((1911 * i + 8171 * (100 -i))% 32767);
}

Or this nasty thing:

int rand(void)
{
static int x[4] = { 0x28ab701c, 0x7158f2fb 0x66be6705 0x3ad15328 };
static int i = 0;

i++;
i %= 4;

return (x ^ __seed);
}

And if that's too awful, would it matter if x had, say, 1000 elements in
it?

Because I remember rand() under Ultrix circa 1992 had a very short
period... but I'm confident it fits the Standard's idea of
"pseudo-random". (It would also alternate even/odd.)

-Beej
 
K

Keith Thompson

Beej Jorgensen said:
Because I remember rand() under Ultrix circa 1992 had a very short
period... but I'm confident it fits the Standard's idea of
"pseudo-random". (It would also alternate even/odd.)

As I recall, the sample implementation in the standard doesn't have
the even/odd problem (I'll verify that later). It's odd^H^H^H
interesting that some implementations are worse than the one in the
standard. Perhaps they predate it.
 
S

Seebs

That is such an odd remark. I have been asked on several occasions to
do technical reviews of books and articles. Some I've done, but i
don't feel any responsibility for errors in the books and articles
that I declined to review.

The odd thing about it is the surreal assertion that I have some kind
of "vendetta against Schildt as a person". I don't think I'd even thought
about him for most of the seven or eight years between the last time this
came up on Usenet and someone asking me questions about the page last summer.

As to the ferror()/putc() example... Can someone tell me where in the book
this is, more precisely? I have both 3rd and 4th editions, and I'd like
to look and see what it's like in both of those. So, say, what's the chapter
on, and roughly where in the chapter is it? (The 4e book I have doesn't
number listings anymore.)

-s
 
S

Seebs

And in general technical reviews are only done for love because they are
paid so badly that no one could consider them a source of income.

This is what I did not, at the time, realize. Had I understood that, I
might well have done it.

Although honestly, I don't see anything to suggest that it would have
mattered. While the 4th edition of C:TCR does fix some of the issues that
have been raised, it preserves others.

-s
 
B

Beej Jorgensen

As I recall, the sample implementation in the standard doesn't have
the even/odd problem (I'll verify that later).

No, it doesn't seem to, giving it a run. (And it looks like the sample
implementation is unchanged in C89/C99/C1X.)
It's odd^H^H^H interesting that some implementations are worse than
the one in the standard. Perhaps they predate it.

IIRC, this was on a MicroVax II, which Wikipedia says first came out in
1985, so the implementation could be earlier than the standard. Or it
could have just brazenly ignored it. :)

-Beej
 
L

lawrence.jones

Keith Thompson said:
As I recall, the sample implementation in the standard doesn't have
the even/odd problem (I'll verify that later). It's odd^H^H^H
interesting that some implementations are worse than the one in the
standard. Perhaps they predate it.

Almost certainly. The even/odd problem was caused at Berkeley by a well
meaning but clueless individual who increased the range of the generator
(which originally matched the sample implementation) by returning the
*entire* internal state rather than just the high-order bits of it. BSD
was very popular, so that defective generator got around a lot,
unfortunately.
 
K

Keith Thompson

Almost certainly. The even/odd problem was caused at Berkeley by a well
meaning but clueless individual who increased the range of the generator
(which originally matched the sample implementation) by returning the
*entire* internal state rather than just the high-order bits of it. BSD
was very popular, so that defective generator got around a lot,
unfortunately.

Looks about right.

Here's the implementation in the standard, which is reasonably well behaved:

static unsigned long int next = 1;

int rand(void) // RAND_MAX assumed to be 32767
{
next = next * 1103515245 + 12345;
return (unsigned int)(next/65536) % 32768;
}

void srand(unsigned int seed)
{
next = seed;
}

Here's a version modified to return the entire internal state. Only
the return statement is changed.

static unsigned long int next = 1;

int rand(void) // RAND_MAX assumed to be 32767
{
next = next * 1103515245 + 12345;
return next;
}

void srand(unsigned int seed)
{
next = seed;
}

This version does give alternating odd and even results.
 
B

Ben Bacarisse

Seebs said:
As to the ferror()/putc() example... Can someone tell me where in the book
this is, more precisely? I have both 3rd and 4th editions, and I'd like
to look and see what it's like in both of those. So, say, what's the chapter
on, and roughly where in the chapter is it? (The 4e book I have doesn't
number listings anymore.)

The code is as supplied from the publisher for chapter 13 of the 4th
edition. This seems to be about I/O. It is listing 12 of 41 and is
about 38% of the way through the text file.
 
S

Seebs

The code is as supplied from the publisher for chapter 13 of the 4th
edition. This seems to be about I/O. It is listing 12 of 41 and is
about 38% of the way through the text file.

Ayup. Page 321 of the 4th edition.

That really is stupid.

Oh, and you'll notice that the previous listing does:

fprintf(fp, "this is a test %d %f", 10, 20.01);
with no newline.

The next example or so (page 322-323, for fread) is beautiful, because
while it actually catches at least one possible error, it goes ahead
and tries to print things anyway -- but since they're read into the
same array they were written from, you probably get values out as though it
"worked".

These really are crappy examples. The fixes to some of the noise
from previous editions just make the idiocy of the examples more
obvious.

-s
 
B

Ben Bacarisse

Seebs said:
Ayup. Page 321 of the 4th edition.

That really is stupid.

Oh, and you'll notice that the previous listing does:

fprintf(fp, "this is a test %d %f", 10, 20.01);
with no newline.

I am tempted to say "what's wrong with that?" but since I don't like
it as an example I can answer that myself. It is not the usual
objection since the fprintf is to a stream that was opened in binary
mode so there is no obvious portability need for a terminating
newline.

My objection is to writing what is plainly text to a binary stream.
C's text files serve a purpose and there is no reason to subvert the
mechanism in such a simple example. If I opened the stream in text
mode then I would, of course, put \n there, but I am not sure its
absence is the key problem with the code as shown.

Listing 14, BTW, does write a final line to a text stream with no
terminating new line.

I confess to being rather surprised at the number of errors (yes, I
know this is hardly news, but I'd never seen any of the code before
and the effect is much more striking first-hand). The lost
opportunity to teach good, idiomatic C is a real shame. There are
lots of little things like writing

fread(&info, sizeof(struct addr), 1, fp);

rather than the simpler to check:

fread(&info, sizeof info, 1, fp);

along with all the convoluted (and sometimes wrong) input and output
loops. There is the inconsistent layout and inconsistent style. For
example remove is tested "bare" (i.e.'if (remove(argv[1]) ...) but
rename is tested against zero (if (rename(argv[1], argv[2]) != 0) ...

The plain errors are the worst though. I can't tell how many there
are because it is not always easy to tell from the code alone. For
example, listing 10 in chapter 10 shows:

#define ABS(a) (a) < 0 ? -(a) : (a)

which might be there to show how /not/ to write a macro (please tell
me it is).

<snip>
 
S

Seebs

The plain errors are the worst though. I can't tell how many there
are because it is not always easy to tell from the code alone. For
example, listing 10 in chapter 10 shows:

#define ABS(a) (a) < 0 ? -(a) : (a)

which might be there to show how /not/ to write a macro (please tell
me it is).

You lose.

"When this program is compiled, a in the macro definition will be
substituted with the values -1 and 1. The parentheses that enclose
a ensure proper substitution in all cases. For example, if the
parentheses around a were removed, this expression:
ABS(10-20)
would be converted to
10-20 < 0 ? -10-20 : 10-20
after macro replacement and would yield the wrong result."

So, yeah, "all cases" meaning "all cases where the macro is not used in a
larger expression".

Good catch!

-s
 
N

Nick

You understand wrong. If you were at a point where the command entry
routine wanted a keyword, you _could_ not type "IF". You pressed the 'U'
key, and that would result, without any shift keys being needed, in the
'IF' keyword being entered. If you typed 'I' 'F' instead, you'd get
'INPUT' 'F'.
As a side note, you could, and would, use symbol shift, but only to
enter other grammatical parts of commands such as '<' or 'THEN' (and,
anomalously, the 'STOP' keyword). You'd also use it combined with caps
shift to enter "extended mode", in which you could enter less common
keywords such as 'BEEP' or 'ABS'.

In the end, though, it was a pure interpreter, but what you entered was
whole keywords, not text. It was possible, by trickery, to get it to see
the text "IF" rather than the keyword 'IF' where it expected a keyword,
but it wouldn't accept the line if you did so.

The QL had a more conventional input system (plain text, not keywords)
but still did tokenisation and use of high-bit-set characters for
keywords. Every so often a bug could be triggered that turned every
keyword in your program in "PRINT".
 
S

spinoza1111

You lose.

        "When this program is compiled, a in the macro definition will be
        substituted with the values -1 and 1.  The parentheses that enclose
        a ensure proper substitution in all cases.  For example, if the
        parentheses around a were removed, this expression:
                ABS(10-20)
        would be converted to
                10-20 < 0 ? -10-20 : 10-20
        after macro replacement and would yield the wrong result."

So, yeah, "all cases" meaning "all cases where the macro is not used in a
larger expression".

This is incoherent crap. It's well known that you must parenthesize
formal parameters inside macros but it's not a matter of skill. It's a
matter of working around the defects of a language which should not be
used because it's incredibly poorly designed, to the extent that it is
pretentious and silly to talk about "quality" with respect to this
tool.

Schildt, like most real, working computer programmers was not, as you
appear to be, creating the mess, but trying to find a sensible way for
his readers to deal with it on real jobs where they are told by Fat
Bastards and suits to use this mess of a language, so they don't get
fired, you dig?

Arrogance, a loud mouth, and backstabbing, even with the "knowledge"
of workarounds that nobody here can seem to get straight or even
properly remember, aren't "craft" or "skill".

Here we go round the prickly pear
Here we go round the prickly pear
Here we go round the prickly pear
At three o'clock in the morning

-TS Eliot The Hollow Men

You go "round and round" discussing the same issues and making the
same mistakes. At least some of us make new ones, but they are
inevitable in this language.
 
S

spinoza1111

I have a policy to not do a post-publication review of a book that I
have done a technical review of. However one publisher accepted a
technical review from me, used my credentials (without asking) in the
front matter of the book though the author had not acted on the
technical review (that was his decision). Needless to say that publisher
never got another technical review from me. Another time I accidentally
reviewed a book (which was riddles with errors) that I had done a

Did they include the use of the third person singular inflection in
passive voice?
 
S

spinoza1111

May I suggest that it is better not to break up compound
statements across lines without using braces.  Thus use

   keyword(args) statement;

or

   keyword(args) {
      statement;
   }

or even

   keyword(args) {statement;}

but not

   keyword(args)
      statement;

Of course this is a matter of style and many are quite
comfortable with the latter usage.  My view is that it is more
error prone and potentially misleading.  YMMV.

As to the code in question, I would might use the one liner.  If
not I might use a for statement, e.g.,

    for (;*str;str++) {
       if (fputc(*str,fp)==EOF) break;
    }

Richard Harter, [email protected]://home.tiac.net/~cri,http://www.varinoma.com
Infinity is one of those things that keep philosophers busy when they
could be more profitably spending their time weeding their garden.

(Sigh) Even those of us who abandoned C when Visual Basic came out
knew that there are two basic types of preprocessor macros in
practice. Macros intended to return expressions must be surrounded by
round parentheses. Macros intended to return statements must be
surrounded by braces. Most formal parameters must be, in the macro
definition, surrounded by round parentheses since most are intended to
be expressions (usually simple values). But, I suppose that if a macro
is passed a statement, that formal parameter must in the def be
surrounded by braces.

But the fact that this issue even exists is a major flaw of C. The
fact that it's up for grabs here means that before any of you clowns
attack another C author, you need to learn C, including the fact that
as a modern programming language, C is complete horseshit.
 
B

Ben Bacarisse

spinoza1111 said:
This is incoherent crap. It's well known that you must parenthesize
formal parameters inside macros but it's not a matter of skill. It's a
matter of working around the defects of a language which should not be
used because it's incredibly poorly designed, to the extent that it is
pretentious and silly to talk about "quality" with respect to this
tool.

Schildt, like most real, working computer programmers was not, as you
appear to be, creating the mess, but trying to find a sensible way for
his readers to deal with it on real jobs where they are told by Fat
Bastards and suits to use this mess of a language, so they don't get
fired, you dig?

I think you've missed the point. The parentheses around (a) are not
the issue because they are, of course, correct. The problem is the
lack of parentheses around the conditional expression. Why would
someone suggest that ABS might be written that way? It will trip
every beginner up.

Code like that does not help anyone who has to deal with C in a real
job. People like that need correct examples and models of good
style. Why, for example, is he using 'gets'; C's worst function (and
an officially deprecated one) if he is just trying to help people muddle
though with this terrible language?

<snip>
 

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
473,777
Messages
2,569,604
Members
45,228
Latest member
MikeMichal

Latest Threads

Top