Requesting advice how to clean up C code for validating string represents integer

  • Thread starter robert maas, see http://tinyurl.com/uh3t
  • Start date
R

robert maas, see http://tinyurl.com/uh3t

From: Random832 said:
Why was there a loop at all in step 1?

Because after compiling and starting the program and typing a test
value and restarting the program and typing another test value and
restarting the program and typing another test value and restarting
the program and typing another test value, I got fed up with having
to manually re-start the program every time I wanted to type in a
new test value.
 
R

robert maas, see http://tinyurl.com/uh3t

From: Flash Gordon said:
You should use "-ansi -pedantic" as well, together with possibly -W.

Why? What purpose would be served by doing that?
You consider a compiler to be stupid for following the language
specification?

The language specification does not forbid or suggest against
shifting a value to the left to make room for adding another small
bunch of bits on the right. The code as written is perfectly valid,
a suggestion that it ought to be changed to add in the new bits
right on top of the old ones (mangling both) and *then* shifting to
the left (leaving a hole where the new bits should have been) is
not a good suggestion.
Did you actually even go to the effort of trying code before
putting it up on your web site? I think not.

The code for doing the data processing, yes. Didn't you see the
thread where I had a SLEEP call in the test rig to prevent runaway
spew if ctrl-D was pressed to generate EOS on STDIN. After I got
the code for validating string decimal representation of integer
and conversion to actual long long int datatype all working, *then*
I interface it to CGI and put it up, and tried it, and made sure it
was all working before leaving it standing for others to use.

The code for interfacing to CGI, well there's no way to test that
without putting it up on cgi-bin, where anybody might accidently
try it while I'm right in the midst of working on it. There's no
way to avoid that. There's no way for me to run any CGI software
without making it public-available. But I make sure there's a short
period from when I first try interfacing it until it's working, and
it has a WARNING, CODE NOT YET TESTED YET ... at the boundary
between what's already working and what I'm testing at the moment,
just in case somebody else tries it in the middle of a development
period.

I'm probably going to continue the same policy in the future. Any
time I am starting to write a brand-new major algorithm that will
require a lot of work before it's ready for others to try, I'll do
it in a stdio test rig before interfacing it to CGI. But any time
I'm just adding one or two line(s) of code at a time to an existing
script I'll probably put it directly online with that warning ahead
of it. Do you have a serious problem with my policy in this matter??
I'm sorry, but either you failed

I got an "A" in every one of those classes. If you don't believe
me, come here, we'll go to the public library where there's access
to JavaScript (required for viewing transcripts), and I'll show you
my complete DeAnza transcript. If you want to call me a liar in a
public newsgroup, then **** you bastard!!
or those courses based on your current knowledge or they appear
to be almost worthless.

You're entitled to your opinion on such matters. Perhaps you should
come here and look at my transcript to see which instructors were
teaching those classes, and then you write a formal letter to
De Anza College complaining that all those instructors are
incompetant to teach C programming classes.
Your "CookBook" currently seems to be a prime example of why you
should *not* trust web resources.

The primary purpose of my "CookBook" is to show, in several
languages in parallel how to do various common tasks, such as the
tasks provided by standard libraries in the various languages, and
eventually some of the more advanced tasks covered in the Perl and
Common Lisp cookbooks. That should accomplish several purposes:
- If a person is trying to learn a new language, and knows how to
do something in one language but needs to know how to do
something equivalent in the new language, whereby the person can
directly search for the library function in the language and
thereby jump directly to the place where that function is
compared to equivalents in other languages.
- If the person wants to convert one kind of data to another kind,
the person can look in the table of contents to find either type
first and the other type as a sub-heading, and thereby have a
short section of similar functions to browse, not distracted by
other functions that deal with other combinations of data types.
- If a person is trying to pick an appropriate language for some
utility, and has an idea what specific data processing steps
would be involved in the task, the person can look up each
relevant section per processing step and get a idea how well
each language covers that step, and thereby get a general idea
how much extra work would be required, or whether it's even
feasible, in the various languages.

At present my "CookBook" is very far from completion. I have
finished including one c library, and lisp equivalents, and am
starting on two more c libraries. I still need to include the rest
of the c libraries, all the stuff in lisp that has no c equivalent,
and include java equivalents for all of that. Then someday I need
to check differences between c and c++ for this all and show the
c++ way whereever different. I also need to include all the java
stuff that's not available in c or lisp. Also someday I need to
include perl and php equivalents where different from c. And of
course include the perl/php stuff that's not in the other languages
at all. For the moment, I'm concentrating on completeness of
data/processing tasks, not much covering control structures such as
thread or inter-process communication at all. Better to be complete
(eventually, this year I hope) in one major class of processing
tasks, than to jump around willy nilly and never get any particular
class of tasks completely covered in five years. In particular, in
browsing the table of contents of the fine GNU C library document:
<http://www.aquaphoenix.com/ref/gnu_c_library/>
I noticed a large amount of stuff on pipes and sockets, which I've
decided *not* to include on this first major pass, partly because
it'd be the "straw that broke the camel's back" for my workload,
but also because it doesn't fit into the datatype matrix anyway.
I've decided to stick totally with the libraries that process data
types inside the machine, until I get that virtually all done.
Actually I'm not even sure I want to finish the library I started
exploring yesterday, the stuff with floating-point numbers. I might
decide to abort that before investing any more time with it.
I suggest you start looking at the comp.lang.c FAQ (Google will find it)

Is this the one you want me to look at? <http://c-faq.com/>

I browsed it a little, and found one apparent mistake:
<http://c-faq.com/aryptr/arraylval.html>

Q: How can an array be an lvalue, if you can't assign to it?
_________________________________________________________________

A: The term ``lvalue'' doesn't quite mean ``something you can assign
to''; a better definition is ``something that has a location (in
memory).'' [footnote] The ANSI/ISO C Standard goes on to define a
``modifiable lvalue''; an array is not a modifiable lvalue. See also
question 6.5.

In fact you *cannot* assign to an array (except if it was declared
as a formal parameter, in which case it's already degraded to a
simple pointer which *can* be assigned to). You can only assign to
an *element* of an array. For example:
int main(void) {
char name[10] = "John";
name[2] = 'a'; /* Valid, assign to element name is now "Joan". */
name = "Mike"; /* Not legal, assign to *array* itself. */
...
Am I correct there? Thus the question above presumes a false fact,
and the answer should right at the top point out the false premise,
not assume the false premise and issue a red herring of an answer.

Hmmm, curious:
<http://c-faq.com/misc/returnparens.html>
Just the other day somebody corrected me because I followed the
examples/spec in K&R on pages 23, 68, and 70, where the sytax is
repeatedly stated as return(expression). But way back on page 203
it says instead return expression; (no parens), which I noticed
just now for the very first time, in respose to this FAQ item. Is
that a mistake in proofreading in K&R, and if so which was correct
at the time it was written, i.e. were pages 23/68/70 all wrong, or
was page 203 wrong, at the time it was written?
and buy a copy of K&R2

I have no money to buy anything. Please provide me with a job that
pays earned income if you want to change this present condition of
my life.
 
K

Keith Thompson

Why? What purpose would be served by doing that?

It would catch more errors.
The language specification does not forbid or suggest against
shifting a value to the left to make room for adding another small
bunch of bits on the right. The code as written is perfectly valid,
a suggestion that it ought to be changed to add in the new bits
right on top of the old ones (mangling both) and *then* shifting to
the left (leaving a hole where the new bits should have been) is
not a good suggestion.

Quoting what you wrote up-thread:
| In cgis.c (needed for h3.c and beyond), there's a line of code that
| shifts the existing value to the left 4 bits and then adds in the
| four new bits obtained from the hexadecimal character in the string
| it's walking. The line of code looks like this:
| c = c<<4 + h;
| but the gnu c compiler complains:
| cgis.c:118: warning: suggest parentheses around + or - inside shift
| Give that there are clearly extra spacing around the =, while the
| << is compact, it's quite clear the intention of the author was:
| c = (c<<4) + h;
| so it's stupid for the compiler to suggest making it instead:
| c = c<<(4 + h);

You have misunderstood what that expression means. I think somebody
already explained it to you; I'll try again.

The spacing around operators is *ignored* by the compiler, though it
can be useful for legibility and to make your intent clear to the
reader. You wrote:
c = c<<4 + h;
which you apparently wanted to be evaluated as
c = (c<<4) + h;
but it actually *means*
c = c << (4 + h);
because the "+" operator binds more tightly than the "<<" operator.
gcc was kind enough (and clever enough) to warn you about this.

The spacing might convey your intention to a human reader; it does not
convey anything to the compiler.

If you don't believe me, try this program (10 and 17 are just
arbitrary values chosen to cause the expression to give different
results depending on the grouping):

#include <stdio.h>
int main(void)
{
int c = 10;
int h = 17;

if (c<<4 + h == (c<<4) + h) {
printf("c<<4 + h == (c<<4) + h\n");
}

if (c<<4 + h == c<<(4 + h)) {
printf("c<<4 + h == c<<(4 + h)\n");
}
return 0;
}

Another example, that might be clearer:
x+y * z
*looks* like it should mean
(x + y) * z
but it actually means
x + (y * z)

If you find yourself using spacing to indicate grouping in an
expression, I suggest you use parentheses instead.

[...]
The code for interfacing to CGI, well there's no way to test that
without putting it up on cgi-bin, where anybody might accidently
try it while I'm right in the midst of working on it. There's no
way to avoid that.
[...]

<OFF-TOPIC>
There are a number of ways to avoid that; some of them may not be
available to you, depending on the resources to which you have access.

If you're able to set up your own web server, you can probably
configure it so that nobody else can access it, and experiment to your
heart's content.

If that's not possible, and all you can do is install your code in
cgi-bin, you can try installing it with a name that nobody is likely
to stumble across. You can exercise the code because you know its
name, but nobody else can.
</OFF-TOPIC>

If you have questions about CGI, try asking them in
comp.infosystems.www.authoring.cgi.

[snip]
I got an "A" in every one of those classes. If you don't believe
me, come here, we'll go to the public library where there's access
to JavaScript (required for viewing transcripts), and I'll show you
my complete DeAnza transcript. If you want to call me a liar in a
public newsgroup, then **** you bastard!!

Calm down; nobody called you a liar. And consider watching your
language; there's no point in needlessly offending people.
or those courses based on your current knowledge or they appear
to be almost worthless.
[...]
I suggest you start looking at the comp.lang.c FAQ (Google will find it)

Is this the one you want me to look at? <http://c-faq.com/>

I browsed it a little, and found one apparent mistake:
<http://c-faq.com/aryptr/arraylval.html>

Q: How can an array be an lvalue, if you can't assign to it?
_________________________________________________________________

A: The term ``lvalue'' doesn't quite mean ``something you can assign
to''; a better definition is ``something that has a location (in
memory).'' [footnote] The ANSI/ISO C Standard goes on to define a
``modifiable lvalue''; an array is not a modifiable lvalue. See also
question 6.5.

In fact you *cannot* assign to an array (except if it was declared
as a formal parameter, in which case it's already degraded to a
simple pointer which *can* be assigned to). You can only assign to
an *element* of an array.
[...]

Of course. Read the FAQ again, more carefully; it doesn't say or
imply that you can assign to an array. The FAQ is perfectly correct.

[...]
Am I correct there? Thus the question above presumes a false fact,
and the answer should right at the top point out the false premise,
not assume the false premise and issue a red herring of an answer.

The letter 'l' in the word "lvalue" originally referred to the *left*
side of an assignment. The idea was that an "lvalue" was an
expression that can appear on the left side of an assignment, and an
"rvalue" was an expression that can appear on the right side of an
assignment. This terminology predates C, and those meanings may have
been appropriate for earlier, simpler languages. In C, the meaning of
"lvalue" has changed to include any expression that designates an
object, whether it can be assigned to or not (and the term "rvalue"
has been largely dropped).

The question is based on a misconception. Someone who's familiar with
the historical meaning of "lvalue" is likely to be confused by the
fact that an array can be an lvalue, but can't appear on the left side
of an assignment. The whole point of the answer is to correct that
misconception.
Hmmm, curious:
<http://c-faq.com/misc/returnparens.html>
Just the other day somebody corrected me because I followed the
examples/spec in K&R on pages 23, 68, and 70, where the sytax is
repeatedly stated as return(expression). But way back on page 203
it says instead return expression; (no parens), which I noticed
just now for the very first time, in respose to this FAQ item. Is
that a mistake in proofreading in K&R, and if so which was correct
at the time it was written, i.e. were pages 23/68/70 all wrong, or
was page 203 wrong, at the time it was written?

The examples are all correct. The parentheses are *optional*. Both
return(42);
and
return 42;
are perfectly legal.
I have no money to buy anything. Please provide me with a job that
pays earned income if you want to change this present condition of
my life.

I'm sorry if your financial situation is unfavorable, but that
certainly isn't anybody else's responsibility. Complaining here about
things we can't help you with wastes your time and ours.
 
R

Richard Bos

CBFalconer said:
In what way?

In that it's _not_ better to use the feof() function to check for eof.
feof() is good as an aid to distinguish between eof and error _once
you've already checked for EOF_. IOW, it's used with EOF, not better
than.

Richard
 
C

CBFalconer

Richard said:
In that it's _not_ better to use the feof() function to check for
eof. feof() is good as an aid to distinguish between eof and
error _once you've already checked for EOF_. IOW, it's used with
EOF, not better than.

While I agree with your statement above, how does that make GNU
wrong? feof shows the file is at EOF, but not that a read etc.
failed. If it is not at EOF a read may succeed, or may fail due to
reaching EOF, or may fail due to i/o error. I think you are
objecting to the fact that they don't state explicitly that these
calls should be used to resolve the cause of receiving an EOF
signal. We don't know the context of the above quote without going
to the original, which I haven't. 'better' may simply mean better
than assuming receiving EOF means the file is at eof.

--
<http://www.cs.auckland.ac.nz/~pgut001/pubs/vista_cost.txt>
<http://www.securityfocus.com/columnists/423>

"A man who is right every time is not likely to do very much."
-- Francis Crick, co-discover of DNA
"There is nothing more amazing than stupidity in action."
-- Thomas Matthews
 
C

CBFalconer

robert said:
.... snip ...


I have no money to buy anything. Please provide me with a job that
pays earned income if you want to change this present condition of
my life.

Then you might be well advised to listen to at least some of the
advice you are receiving rather than going off in the wilderness
with random insults. Your knowledge shows gaping holes, and by
your own statements that can only be due to the lack of quality in
your education and/or failure to listen. Your performance here
makes the latter more likely.

--
<http://www.cs.auckland.ac.nz/~pgut001/pubs/vista_cost.txt>
<http://www.securityfocus.com/columnists/423>

"A man who is right every time is not likely to do very much."
-- Francis Crick, co-discover of DNA
"There is nothing more amazing than stupidity in action."
-- Thomas Matthews
 
S

santosh

Keith said:
Flash Gordon wrote:
I suggest you start looking at the comp.lang.c FAQ (Google will find it)

Is this the one you want me to look at? <http://c-faq.com/>

I browsed it a little, and found one apparent mistake:
<http://c-faq.com/aryptr/arraylval.html>

Q: How can an array be an lvalue, if you can't assign to it?
_________________________________________________________________

A: The term ``lvalue'' doesn't quite mean ``something you can assign
to''; a better definition is ``something that has a location (in
memory).'' [footnote] The ANSI/ISO C Standard goes on to define a
``modifiable lvalue''; an array is not a modifiable lvalue. See also
question 6.5.

In fact you *cannot* assign to an array (except if it was declared
as a formal parameter, in which case it's already degraded to a
simple pointer which *can* be assigned to). You can only assign to
an *element* of an array.
[...]

Of course. Read the FAQ again, more carefully; it doesn't say or
imply that you can assign to an array. The FAQ is perfectly correct.

[...]
Am I correct there? Thus the question above presumes a false fact,
and the answer should right at the top point out the false premise,
not assume the false premise and issue a red herring of an answer.

The letter 'l' in the word "lvalue" originally referred to the *left*
side of an assignment. The idea was that an "lvalue" was an
expression that can appear on the left side of an assignment, and an
"rvalue" was an expression that can appear on the right side of an
assignment. This terminology predates C, and those meanings may have
been appropriate for earlier, simpler languages. In C, the meaning of
"lvalue" has changed to include any expression that designates an
object, whether it can be assigned to or not (and the term "rvalue"
has been largely dropped).

If so, is there a reason to retain that term at all, and not use a
more generic term like expression?

<snip>
 
C

Chris Dollin

Keith said:
The letter 'l' in the word "lvalue" originally referred to the *left*
side of an assignment. The idea was that an "lvalue" was an
expression that can appear on the left side of an assignment,

Actually no. The idea was that an lvalue was the /value/ that was
obtained by evaluating an expression which was to be assigned
to, ie, traditionally [but not exclusively] on the left-hand-side
of an assignment.
and an "rvalue" was an expression that can appear on the right
side of an assignment.

Similarly, "rvalue" meant the /value/ obtained by evaluating an
expression for its "ordinary", not-being-assigned-to, value,
traditionally the right-hand-side of an assignment.

In the assignment `L := R`, we find L's lvalue and R's rvalue,
and then do some assignment magic which puts the rvalue "into"
the lvalue, which means [absent side-effects ...] that L's
rvalue is now [maybe some conversion of] what R's rvalue was.

Part of the reason for introducing this distinction was to
formalise why the variable `a` in `a := a + 1` means two
different things in the two different places: the left-hand
`a` is evaluated for its lvalue and the right-hand one for
its rvalue. For a variable this typically means evaluating
its lvalue and then dereferencing that.

In some languages, literals have lvalues, so the assignment
`1 := 2` is legal. Depending on the language semantics, `1`
may have a single lvalue, or a different one each time it
is evaluated. (The rvalue of `1` might or might not use its
lvalue.) While for assignment this looks like the rabid
and hungry sabre-toothed tiger, it makes more sense for
parameter-passing ...
This terminology predates C,

having been introduced or popularised by, if I recall,
Christopher Strachey, in the late 60's-early 70's; it
turns up (ditto) in his /Fundamental Concepts in Programming
Languages/ which a quick google doesn't find (references,
yes, text, no). My paper copy is somewhere at home.
and those meanings may have been appropriate for earlier,
simpler languages.

In fact they can work for modern languages -- many of which
are /simpler/ in these respects than some earlier languages.
In C, the meaning of "lvalue" has changed to include any
expression that designates an object, whether it can be
assigned to or not

That still fits inside the original formulation: the lvalue
is the value you get /by evaluating on the left/; you may
then be able to store into (through?) it, or not.

(I agree there's a shift to calling the /expression/ the
lvalue, rather than its /value/ the lvalue. I shall
spare you what some people might be moved to call a
"hissy fit" about this.)
(and the term "rvalue" has been largely dropped).

In favour of "value", isn't it?

C has (at least) three modes for expression evaluation:
lvalue, (r)value, and what one might call "svalue",
evaluation as the operand of `sizeof`.
 
K

Keith Thompson

santosh said:
Keith Thompson wrote: [...]
The letter 'l' in the word "lvalue" originally referred to the *left*
side of an assignment. The idea was that an "lvalue" was an
expression that can appear on the left side of an assignment, and an
"rvalue" was an expression that can appear on the right side of an
assignment. This terminology predates C, and those meanings may have
been appropriate for earlier, simpler languages. In C, the meaning of
"lvalue" has changed to include any expression that designates an
object, whether it can be assigned to or not (and the term "rvalue"
has been largely dropped).

If so, is there a reason to retain that term at all, and not use a
more generic term like expression?

The C standard has done just that. There are exactly two occurrences
of the word "rvalue" in the C99 standard. One is in a footnote in
6.3.2.1:

[...]
What is sometimes called "rvalue" is in this International
Standard described as the "value of an expression".

The other is the index entry referring to this footnote.

C90 has the same wording.
 
K

Keith Thompson

Chris Dollin said:
Keith said:
The letter 'l' in the word "lvalue" originally referred to the *left*
side of an assignment. The idea was that an "lvalue" was an
expression that can appear on the left side of an assignment,

Actually no. The idea was that an lvalue was the /value/ that was
obtained by evaluating an expression which was to be assigned
to, ie, traditionally [but not exclusively] on the left-hand-side
of an assignment.

Ah, that makes sense.
Similarly, "rvalue" meant the /value/ obtained by evaluating an
expression for its "ordinary", not-being-assigned-to, value,
traditionally the right-hand-side of an assignment.

And that explains why that footnote says that an rvalue is the *value*
of the expression, while an lvalue has come to refer to the expression
itself. Thanks for the clarification.
 
R

robert maas, see http://tinyurl.com/uh3t

From: Keith Thompson said:
It would catch more errors.

More likely generate bogus errors. For example:

% more tryll.c
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
...
(the declaration for strtoll is located in stdlib.h)
Reference:
<http://www.delorie.com/gnu/docs/glibc/libc_423.html>
20.11.1 Parsing of Integers
The `str' functions are declared in `stdlib.h' ...
...
Function: long long int strtoll (const char *restrict string, char
**restrict tailptr, int base)

% gcc tryll.c -Wall
(compiles without warnings)

% gcc tryll.c -Wall -ansi
tryll.c: In function `tryParseLliTalk':
tryll.c:53: warning: implicit declaration of function `strtoll'
(that's a totally bogus warning, given that stdlib.h is included)

Perhaps -ansi might be of some value later when I'm writing actual
examples of how to do specific things. But right now strtoll is
used only to convert the decoded HTML FORM field from string to
integer so that I can *later* use that numeric value to demonstrate
arithmetic and other functions that require integers as input,
allowing the user to vary the particular integer value being used
as input simply by changing the contents of the form field.

% gcc tryll.c -Wall -pedantic
In file included from tryll.c:3:
/usr/include/stdlib.h:111: warning: ANSI C does not support `long long'
/usr/include/stdlib.h:117: warning: ANSI C does not support `long long'
tryll.c:5: warning: ANSI C does not support `long long'
tryll.c: In function `printflld':
tryll.c:6: warning: ANSI C does not support the `ll' length modifier
tryll.c:11: warning: ANSI C does not support `long long'
tryll.c: At top level:
tryll.c:25: warning: ANSI C does not support `long long'
tryll.c: In function `mystrtoll':
tryll.c:27: warning: ANSI C does not support `long long'
tryll.c: In function `tryParseLliTalk':
tryll.c:49: warning: ANSI C does not support `long long'
tryll.c:57: warning: ANSI C does not support the `ll' length modifier
tryll.c:62: warning: ANSI C does not support the `ll' length modifier

That's even worse at emitting worthless crap that's of no use to me
at this time. Maybe later when I'm making examples of code, this
might allow me to flag anything that's not usable outside the GNU
environment. For now, that would just present so much noise that
I'd never see a signal of an *actual* error in my code.

% gcc tryll.c -Wall -W
(compiles without any warnings)
You wrote:
c = c<<4 + h;
which you apparently wanted to be evaluated as
c = (c<<4) + h;
but it actually *means*
c = c << (4 + h);
because the "+" operator binds more tightly than the "<<" operator.
gcc was kind enough (and clever enough) to warn you about this.

Ah, well I didn't write that, Peter Burden wrote it, see link here:
<http://www.rawbw.com/~rem/HelloPlus/hellos.html#c3>
So you're saying his code has a bug in it?
Hmm, I tried putting special characters into the FirstName field in that
form, and indeed it failed to decode it correctly. For example,
when I enter into the field
foo&baz
it gets urlencoded as
firstname=foo%26baz
but Peter's decoder give me:
For key [firstname] the value is [foo].
which is probably actually internally
foo<NUL>baz
where <NUL> prematurely ends the %s printf of the string.

Let me try putting parens there to make the nesting of operators
correct, done, recompiling cgis.c, done, rebuilding h3-c.cgi, done,
re-testing, horay, the bug is fixed, it now gives:
For key [firstname] the value is [foo&baz].

Thank you very much for the heads-up on this bug in Peter's code.
Now I need to comment that change I made in the code, done, and
update my description of it in hellos.html, done!!
If you don't believe me, try this program ...

I didn't need to. I just keyed special characters such as & and <
into my Web form, observed the hexadecimal encoding of them when I
asked lynx to show me the full URI (using GET method the urlencoded
form contents are after the ? mark in the URI), and then compared
to what came through after decoding as I showed above.
If you find yourself using spacing to indicate grouping in an
expression, I suggest you use parentheses instead.

Any time I need to look at the operator precedence table, it means
I shouldn't bother, use parens instead. That's what I do in all my
code. But this was Peters, and it was posted for public use, and
despite one mismatched prototype/definition pair (which I fixed,
and assumed had been left in because his compiler treated the two
as the same whereas mine doesn't), I assumed the basic algorithms
had been tested before posting. I guess I assumed too much. I never
did a complete line-by-line examination of his code to make sure it
looked correct, although now I did a line-by-line browse of it just
to see if anything else was obviously questionable, as well as to
find that troubling line of code again and see if it was the only
case of that particular problem.

So operator precence fooled Peter, and fooled me too, and Peter
didn't bother to unit-test each line of his code, and I just
assumed he had done so before posting his code to the net for
others to use. When I write code, I unit test *every* line of code,
even the most trivial of things, just to make sure I didn't make
some really really stupid typographic error, before I go on to the
next line of code. In lisp that style of developing code comes
totally naturally without any pain. In c it's a royal pain, which
is one of many reasons I hate to write software in c. For an actual
example of how I develop code with line-by-line unit testing, see:
<http://www.rawbw.com/~rem/HelloPlus/CookBook/CookTop.html#stru>
(From the table of contents, in chapter 2, the section "Overall
structure of a program")
then search for the paragraph that begins:
Here's my preferred way to develop lisp software: Bottom-up overall,
input-forward within each level, unit-test each line of code before
incorporating it into a block of code, unit-test the completed block
before building a function around it, unit test the resultant function
before moving on to start work on the next. ...
and read the annotated transcript that follows.
<OFF-TOPIC>
There are a number of ways to avoid that; some of them may not be
available to you, depending on the resources to which you have access.
If you're able to set up your own web server, ...

Not available to me. No money to lease office space and purchase
equipment, nor to lease space on a commercial server farm.
If that's not possible, and all you can do is install your code in
cgi-bin, you can try installing it with a name that nobody is likely
to stumble across. You can exercise the code because you know its
name, but nobody else can.

But I'll be incrementally adding to existing CGI application, and
it's a royal pain to make a complete copy of everything (actual
program modules on cgi-bin, Web page with forms for exercising it
in GET and POST mode), and even if I do all that, I still have the
task of folding everything back into the main files, during which
there's a "flag day" when a mix of old and new stuff is
inconsistent. Since this isn't a major commerical service like the
Google search engine with millions or even thousands of users, I
consider it reasonble that new stuff is simply installed directly
online with a suitable warning for the zero or one users who happen
to bump into it during the few minutes it takes to complete the CGI
interfacing of the new module I already got debugged in a stdio
test rig. If I thought I had more than two users during any one
day, of which there was a good chance one of them would encounter
the temporary under-construction state, I might reconsider. At
present I have a couple other much more valuable services which
each gets used by somebody other than myself only about once in two
to six months.

Have you personally *ever* tried one of my CGI applications and
encountered a server abort, or obviously truncated output, because
the program crashed at the start (before transmitting the
CGI-MIME-type header) or in the middle respectively, because I had
just installed something new and it had a horrible bug? Have you
even see it produce obviously partial new output, where each time
you'd refresh it'd show a little bit more as I added line by line
of new code at the bottom? Has anyone reading this thread
encountered such work-in-progress ever?
If you have questions about CGI, try asking them in
comp.infosystems.www.authoring.cgi.

I don't have any such questions at the present. But if and when I
ever decide to generate cookies, I might ask there, thanks for the
pointer.

More reply later...
 
S

santosh

robert said:
More likely generate bogus errors. For example:

% more tryll.c
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
..
(the declaration for strtoll is located in stdlib.h)
Reference:
<http://www.delorie.com/gnu/docs/glibc/libc_423.html>
20.11.1 Parsing of Integers
The `str' functions are declared in `stdlib.h' ...
...
Function: long long int strtoll (const char *restrict string, char
**restrict tailptr, int base)

% gcc tryll.c -Wall
(compiles without warnings)

% gcc tryll.c -Wall -ansi
tryll.c: In function `tryParseLliTalk':
tryll.c:53: warning: implicit declaration of function `strtoll'
(that's a totally bogus warning, given that stdlib.h is included)

It's not. It means that the prototype for strtoll() *isn't* included
in stdlib.h, but it's object code is present in the linker's path.
That's why it links fine but complains about missing prototype when
compiled at a higher warning level. Manually search include files like
stdlib.h, stdint.h, inttypes.h, string.h etc., for strtoll(). If you
don't find it's prototype, then write your own, as per the standard.
It's likely to work.

% gcc tryll.c -Wall -pedantic
In file included from tryll.c:3:
/usr/include/stdlib.h:111: warning: ANSI C does not support `long long'
/usr/include/stdlib.h:117: warning: ANSI C does not support `long long'
tryll.c:5: warning: ANSI C does not support `long long'
tryll.c: In function `printflld':
tryll.c:6: warning: ANSI C does not support the `ll' length modifier
tryll.c:11: warning: ANSI C does not support `long long'
tryll.c: At top level:
tryll.c:25: warning: ANSI C does not support `long long'
tryll.c: In function `mystrtoll':
tryll.c:27: warning: ANSI C does not support `long long'
tryll.c: In function `tryParseLliTalk':
tryll.c:49: warning: ANSI C does not support `long long'
tryll.c:57: warning: ANSI C does not support the `ll' length modifier
tryll.c:62: warning: ANSI C does not support the `ll' length modifier

That's even worse at emitting worthless crap that's of no use to me
at this time. Maybe later when I'm making examples of code, this
might allow me to flag anything that's not usable outside the GNU
environment. For now, that would just present so much noise that
I'd never see a signal of an *actual* error in my code.

I personally prefer to set the diagnostic level high. If it's really a
benign warning, I ignore it. Silencing the compiler means you're not
taking full advantage of it's automated analysis, something that
computers are quite good at.

<snip>
 
J

Joe Wright

Keith said:
Chris Dollin said:
Keith said:
The letter 'l' in the word "lvalue" originally referred to the *left*
side of an assignment. The idea was that an "lvalue" was an
expression that can appear on the left side of an assignment,
Actually no. The idea was that an lvalue was the /value/ that was
obtained by evaluating an expression which was to be assigned
to, ie, traditionally [but not exclusively] on the left-hand-side
of an assignment.

Ah, that makes sense.
Similarly, "rvalue" meant the /value/ obtained by evaluating an
expression for its "ordinary", not-being-assigned-to, value,
traditionally the right-hand-side of an assignment.

And that explains why that footnote says that an rvalue is the *value*
of the expression, while an lvalue has come to refer to the expression
itself. Thanks for the clarification.
An lvalue is an expression which allows the compiler to know the address
of an object, perhaps for purposes of assignment. The value of that
object is not really of interest.

Given:

int a, b;

a = 0;
b = 1;

Expressions a and b are both lvalues in the previous two lines. Nobody
cares the prior values of a or b.

a = b;

Now, a is the lvalue and b is not (an expression not an lvalue is an
rvalue). At this point the rvalue of b is 1 and nobody cares the rvalue
of a, the lvalue (address) of a is needed here. Now a == b.
 
F

Flash Gordon

robert maas, see http://tinyurl.com/uh3t wrote, On 16/02/07 21:20:
More likely generate bogus errors. For example:

Nope. Well, -W warns about some things that are not necessarily
problems, but -ansi and -pedantic are very valuable.
% more tryll.c
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
..
(the declaration for strtoll is located in stdlib.h)
Reference:
<http://www.delorie.com/gnu/docs/glibc/libc_423.html>
20.11.1 Parsing of Integers
The `str' functions are declared in `stdlib.h' ...
...
Function: long long int strtoll (const char *restrict string, char
**restrict tailptr, int base)

Well, here you are failing to understand that there is more than one
version of the standard. -ansi invokes gcc in compliant (bar bugs) C89
mode, if you want things from C99 then you can use -std=c99 but you have
to understand that gcc does not fully conform to C89 or C99 in this mode.
% gcc tryll.c -Wall
(compiles without warnings)

% gcc tryll.c -Wall -ansi
tryll.c: In function `tryParseLliTalk':
tryll.c:53: warning: implicit declaration of function `strtoll'
(that's a totally bogus warning, given that stdlib.h is included)

Nope, it is totally correct. Read the man pages.

Perhaps -ansi might be of some value later when I'm writing actual

Actually, it is best to *start* with the compiler with the highest
warning level and only lower it as and when you understand why the
warnings are a good idea and know enough to know why they do not apply
in your specific situation. You currently do not know enough you you
would have found out about -std as well.

Ah, well I didn't write that, Peter Burden wrote it, see link here:
<http://www.rawbw.com/~rem/HelloPlus/hellos.html#c3>
So you're saying his code has a bug in it?

Why should it not? Do you have evidence that Peter Burden never makes
mistakes?
So operator precence fooled Peter, and fooled me too, and Peter
didn't bother to unit-test each line of his code, and I just
assumed he had done so before posting his code to the net for
others to use.

If you post stuff for people to use or link to it from your tutorial it
is *your* responsibility to test it out.

You have failed to fix the other errors pointed out. It would be better
in my opinion to take the page down or add a big warning at the top
saying "CONTAINS MAJOR FACTUAL ERRORS" rather than leaving it up as it is.
 
F

Flash Gordon

robert maas, see http://tinyurl.com/uh3t wrote, On 16/02/07 05:25:
The code for doing the data processing, yes. Didn't you see the

Yes. Did you see the code I pointed out that will not even compile? If
you post code that does not compile I think it is reasonable to assume
that you have not tested it.
I got an "A" in every one of those classes. If you don't believe
me, come here, we'll go to the public library where there's access
to JavaScript (required for viewing transcripts), and I'll show you
my complete DeAnza transcript. If you want to call me a liar in a
public newsgroup, then **** you bastard!!

If you got an A in all of them then the second part of my statement applies.
You're entitled to your opinion on such matters. Perhaps you should
come here and look at my transcript to see which instructors were
teaching those classes, and then you write a formal letter to
De Anza College complaining that all those instructors are
incompetant to teach C programming classes.

If you pay my air fares and for my time at normal consulting rates
(normal for me, that is) I will be happy to. Or you could complain to
them yourself about the fact that people who do know the languages think
that you do not.
The primary purpose of my "CookBook" is to show, in several
languages in parallel how to do various common tasks, such as the
tasks provided by standard libraries in the various languages, and

At the moment it does one of two things depending on the level of
knowledge of the reader. It either shows your lack of knowledge or it
leads the reader up the garden path.
eventually some of the more advanced tasks covered in the Perl and
Common Lisp cookbooks. That should accomplish several purposes:
- If a person is trying to learn a new language, and knows how to

<snip>

Currently it won't show people how to do anything.
At present my "CookBook" is very far from completion. I have

At the moment what you have up there is far from correct.
finished including one c library, and lisp equivalents, and am
starting on two more c libraries. I still need to include the rest

No, you need to start at the beginning and correct all the things you
have got wrong.

Is this the one you want me to look at? <http://c-faq.com/>

Yes. Others have already pointed out that the things you thought were
wrong were in fact completely correct. Do you think that a group that
sometimes has members who are on the standard committee present,
sometimes has major authors of implementations of the standard C library
(and who make their living off said implementation) etc would have a FAQ
with major errors? I'm not in any of those categories and have only
about 12 years experience in C (but rather longer in professional
software development) so you should listen to the many people here who
know the language better than me. You should also take note of the
things I post that they do not correct, because believe me when I make a
mistake it gets corrected.
I have no money to buy anything. Please provide me with a job that
pays earned income if you want to change this present condition of
my life.

Your finances are your problem. You putting up a seriously flawed page
about programming is a problem for any unsuspecting person who comes
across it and for those who have to pick up the pieces from their
learning incorrect information.
 
K

Keith Thompson

More likely generate bogus errors. For example:

% more tryll.c
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
..
(the declaration for strtoll is located in stdlib.h)
Reference:
<http://www.delorie.com/gnu/docs/glibc/libc_423.html>
20.11.1 Parsing of Integers
The `str' functions are declared in `stdlib.h' ...
...
Function: long long int strtoll (const char *restrict string, char
**restrict tailptr, int base)

% gcc tryll.c -Wall
(compiles without warnings)

% gcc tryll.c -Wall -ansi
tryll.c: In function `tryParseLliTalk':
tryll.c:53: warning: implicit declaration of function `strtoll'
(that's a totally bogus warning, given that stdlib.h is included)

No, it is not a bogus warning. I explained this to you at length four
days ago. See
Perhaps -ansi might be of some value later when I'm writing actual
examples of how to do specific things. But right now strtoll is
used only to convert the decoded HTML FORM field from string to
integer so that I can *later* use that numeric value to demonstrate
arithmetic and other functions that require integers as input,
allowing the user to vary the particular integer value being used
as input simply by changing the contents of the form field.

% gcc tryll.c -Wall -pedantic
In file included from tryll.c:3:
/usr/include/stdlib.h:111: warning: ANSI C does not support `long long'
/usr/include/stdlib.h:117: warning: ANSI C does not support `long long'
[snip]

The "-ansi" option tells gcc to support the C89/C90 standard. If you
really need long long and strtoll, you should use "-std=c99" instead
of "-ansi". (gcc does not fully support the C99 standard, but it does
support a fairly good fraction of it.) If you *don't* really need
integers bigger than 32 bits, you might consider using "long" and
"strtol" rather than "long long" and "strtoll"; then "-ansi" shouldn't
have anything to complain about.

(To be clear, I'm not telling you that you don't need integers bigger
than 32 bits; I'm advising you on what you can do *if* you don't need
integers bigger than 32 bits.)

[snip]
Ah, well I didn't write that, Peter Burden wrote it, see link here:
<http://www.rawbw.com/~rem/HelloPlus/hellos.html#c3>
So you're saying his code has a bug in it?

Apparently so. But I wasn't responding just to the code; I was
responding to your incorrect claim that gcc's warning was stupid.

You *assumed* that you knew what the expression meant, and that gcc's
warning was incorrect. It was entirely conceivable that you were
right; after all, the authors of gcc are imperfect humans, just like
the rest of us. But whenever you see a compiler warning, you
shouldn't assume that it's bogus unless you're sure that you
completely understand *why* it's bogus. The gcc authors are pretty
smart; they make mistakes, but that's not the way to bet in most
cases.

[...]
If that's not possible, and all you can do is install your code in
cgi-bin, you can try installing it with a name that nobody is likely
to stumble across. You can exercise the code because you know its
name, but nobody else can.

But I'll be incrementally adding to existing CGI application, and
it's a royal pain to make a complete copy of everything [...]

Have you personally *ever* tried one of my CGI applications and
encountered a server abort, or obviously truncated output, because
the program crashed at the start (before transmitting the
CGI-MIME-type header) or in the middle respectively, because I had
just installed something new and it had a horrible bug? Have you
even see it produce obviously partial new output, where each time
you'd refresh it'd show a little bit more as I added line by line
of new code at the bottom? Has anyone reading this thread
encountered such work-in-progress ever?

To the best of my knowledge, I have never used one of your CGI
applications at all, and frankly I don't much care how they work
unless they raise interesting issues about C.
 
C

CBFalconer

More likely generate bogus errors. For example:

% more tryll.c
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
..
(the declaration for strtoll is located in stdlib.h)
Reference:
<http://www.delorie.com/gnu/docs/glibc/libc_423.html>
20.11.1 Parsing of Integers
The `str' functions are declared in `stdlib.h' ...
...
Function: long long int strtoll (const char *restrict string, char
**restrict tailptr, int base)

% gcc tryll.c -Wall
(compiles without warnings)

% gcc tryll.c -Wall -ansi
tryll.c: In function `tryParseLliTalk':
tryll.c:53: warning: implicit declaration of function `strtoll'
(that's a totally bogus warning, given that stdlib.h is included)

You are exposing your ignorance again. long long is only available
in C99 up. For gcc, -ansi instructs it to use the C90 standard,
which it has done, and found no such thing as strtoll in stdlib.h.

--
<http://www.cs.auckland.ac.nz/~pgut001/pubs/vista_cost.txt>
<http://www.securityfocus.com/columnists/423>

"A man who is right every time is not likely to do very much."
-- Francis Crick, co-discover of DNA
"There is nothing more amazing than stupidity in action."
-- Thomas Matthews
 
C

CBFalconer

Flash said:
robert maas, see http://tinyurl.com/uh3t wrote:
.... snip ...

Your finances are your problem. You putting up a seriously flawed page
about programming is a problem for any unsuspecting person who comes
across it and for those who have to pick up the pieces from their
learning incorrect information.

The two facts may be connected. Any smart potential employer would
look around for independant info on a prospective employee. If
that employer happens to know C fairly well he will discover how
clueless and arrogant Maas is.

--
<http://www.cs.auckland.ac.nz/~pgut001/pubs/vista_cost.txt>
<http://www.securityfocus.com/columnists/423>

"A man who is right every time is not likely to do very much."
-- Francis Crick, co-discover of DNA
"There is nothing more amazing than stupidity in action."
-- Thomas Matthews
 
R

robert maas, see http://tinyurl.com/uh3t

From: Keith Thompson said:
This terminology predates C, and those meanings may have been
appropriate for earlier, simpler languages.

I can understand why K&R might have used such obsolete jargon,
before it was fully realized how confusing it is, but I see no
excuse for current online documentation, especially FAQs to
continue to perpetuate such misleading obsolete jargon.
In C, the meaning of "lvalue" has changed to include any
expression that designates an object, whether it can be assigned
to or not (and the term "rvalue" has been largely dropped).

That's completely wrong. A simple variable is an lvalue, but it's
not an object, it's a primitive type. (And in the jargon of OOP,
nothing whatsoever in C is an object. But using the older lisp
jargon, an array is an object but a simple variable isn't.)
I'm sorry if your financial situation is unfavorable, but that
certainly isn't anybody else's responsibility.

It *is* your responsibility if you tell me to spend money I don't
have after I've already told you of my situation. So in the future...
DON'T!
 
R

robert maas, see http://tinyurl.com/uh3t

From: (e-mail address removed) (Richard Bos)
In that it's _not_ better to use the feof() function to check for
eof. feof() is good as an aid to distinguish between eof and
error _once you've already checked for EOF_. IOW, it's used with
EOF, not better than.

I take your advice for best practice is first check return value to
see if it's negative or whatever the criterion is for unsuccessful,
and if unsuccessful then check feof() and errno to diagnose why it
failed?
 

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,768
Messages
2,569,574
Members
45,051
Latest member
CarleyMcCr

Latest Threads

Top