# Why in hash function use 5381?

Discussion in 'C Programming' started by anguo, Jan 3, 2004.

1. ### anguoGuest

i find in many hash function use 5381,for exampla:
static constmap_hash hash(char *pchData, int iLen)
{
unsigned char cBuf;
constmap_hash ulHashId;
ulHashId = 5381;
while (iLen > 0)
{
cBuf = *pchData++ - 'A';
if (cBuf <= 'Z' - 'A')
{
cBuf += 'a' - 'A';
}
ulHashId = ((ulHashId << 5) + ulHashId) ^ cBuf;
--iLen;
}
return ulHashId;
}
Can anyone tell me why use 5381 ?
thanks!!

anguo, Jan 3, 2004

2. ### Ben PfaffGuest

(anguo) writes:

> i find in many hash function use 5381,for exampla:

[...]

> Can anyone tell me why use 5381 ?

This webpage implies that it is a random number selected by Dan
Bernstein: <http://www.cs.yorku.ca/~oz/hash.html>. Presumably
everyone else just used the same number.
--
int main(void){char p[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz.\
\n",*q="kl BIcNBFr.NKEzjwCIxNJC";int i=sizeof p/2;char *strchr();int putchar(\
);while(*q){i+=strchr(p,*q++)-p;if(i>=(int)sizeof p)i-=sizeof p-1;putchar(p\
);}return 0;}

Ben Pfaff, Jan 3, 2004

3. ### Martin AmbuhlGuest

Ben Pfaff wrote:
> (anguo) writes:
>>i find in many hash function use 5381,for exampla:

> [...]
>>Can anyone tell me why use 5381 ?

> This webpage implies that it is a random number selected by Dan
> Bernstein: <http://www.cs.yorku.ca/~oz/hash.html>. Presumably
> everyone else just used the same number.

Except that it is not so very random looking: 5381 = 012405. This looks
like something deeper is involved. The 001/010/100/000/101 raises the
question about the choice of the last octal digit, though.

--
Martin Ambuhl

Martin Ambuhl, Jan 3, 2004
4. ### Jean-Michel CollardGuest

Ben Pfaff wrote:

>
> --
> int main(void){char p[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz.\
> \n",*q="kl BIcNBFr.NKEzjwCIxNJC";int i=sizeof p/2;char *strchr();int putchar(\
> );while(*q){i+=strchr(p,*q++)-p;if(i>=(int)sizeof p)i-=sizeof p-1;putchar(p\
> );}return 0;}

huh "Just another C hacker"

Ben.c: (in function main)
Ben.c:9:18: Variable i initialized to type arbitrary unsigned integral type,
expects int: sizeof(p) / 2

Ben.c:10:9: Function strchr shadows outer declaration
An outer declaration is shadowed by the local declaration.

Specification of strchr:
[function (char *, int) returns char *]

Ben.c:11:7: Function putchar shadows outer declaration
Specification of putchar:
[function (int) returns int]

Ben.c:12:10: Test expression for while not boolean, type char: *q
Test expression type is not boolean.

Ben.c:14:12: Variable strchr used before definition
An rvalue is used that may not be initialized to a value on some execution
path.
Ben.c:17:7: Variable putchar used before definition

Ben.c:17:7: Return value (type int) ignored: putchar(p)
Result returned by function call is not used.

Cheers

Jean-Michel Collard, Jan 3, 2004
5. ### Ben PfaffGuest

Jean-Michel Collard <> writes:

> Ben Pfaff wrote:
>
> > --
> > int main(void){char p[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz.\
> > \n",*q="kl BIcNBFr.NKEzjwCIxNJC";int i=sizeof p/2;char *strchr();int putchar(\
> > );while(*q){i+=strchr(p,*q++)-p;if(i>=(int)sizeof p)i-=sizeof p-1;putchar(p\
> > );}return 0;}

>
> huh "Just another C hacker"
>
> [...many warnings snipped...]

It's perfectly well-defined, if obfuscated, C. It's not meant to
be lint-clean. Based on what I've seen from some versions of
lint, a lot of lint warnings are simply nonsensical, so that's
not even a good goal for real-world code.

Ben Pfaff, Jan 3, 2004
6. ### Richard BosGuest

Jean-Michel Collard <> wrote:

> Ben Pfaff wrote:
>
> > int main(void){char p[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz.\
> > \n",*q="kl BIcNBFr.NKEzjwCIxNJC";int i=sizeof p/2;char *strchr();int putchar(\
> > );while(*q){i+=strchr(p,*q++)-p;if(i>=(int)sizeof p)i-=sizeof p-1;putchar(p\
> > );}return 0;}

>
> huh "Just another C hacker"
>
> Ben.c: (in function main)
> Ben.c:9:18: Variable i initialized to type arbitrary unsigned integral type,
> expects int: sizeof(p) / 2

Correct for this constant value, though.

> Ben.c:10:9: Function strchr shadows outer declaration
> An outer declaration is shadowed by the local declaration.

Where, pray, is this "outer declaration" to be found?

> Ben.c:11:7: Function putchar shadows outer declaration

And ditto?

> Ben.c:12:10: Test expression for while not boolean, type char: *q
> Test expression type is not boolean.

Yer_what_?

> Ben.c:14:12: Variable strchr used before definition
> An rvalue is used that may not be initialized to a value on some execution
> path.
> Ben.c:17:7: Variable putchar used before definition

Erm... boggle.

> Ben.c:17:7: Return value (type int) ignored: putchar(p)
> Result returned by function call is not used.

Gosh. Lint really _is_ prehistoric, isn't it?

Richard

Richard Bos, Jan 5, 2004
7. ### August DerlethGuest

Richard Bos wrote:
> Jean-Michel Collard <> wrote:
>
>
>>Ben Pfaff wrote:
>>
>>
>>>int main(void){char p[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz.\
>>> \n",*q="kl BIcNBFr.NKEzjwCIxNJC";int i=sizeof p/2;char *strchr();int putchar(\
>>>);while(*q){i+=strchr(p,*q++)-p;if(i>=(int)sizeof p)i-=sizeof p-1;putchar(p\
>>>);}return 0;}

>>
>>huh "Just another C hacker"
>>
>>Ben.c: (in function main)
>>Ben.c:9:18: Variable i initialized to type arbitrary unsigned integral type,
>> expects int: sizeof(p) / 2

>
>
> Correct for this constant value, though.

Eh, lint can't tell that.

>
>
>>Ben.c:10:9: Function strchr shadows outer declaration
>> An outer declaration is shadowed by the local declaration.

>
>
> Where, pray, is this "outer declaration" to be found?

The old-style implicit declaration of everything returning an int?

>>Ben.c:12:10: Test expression for while not boolean, type char: *q
>> Test expression type is not boolean.

>
>
> Yer_what_?

Here's where lint is a bit too pedantic (well, here's a single instance
out of possibly thousands ): C acts like it has a boolean type
sometimes, and it certainly has a boolean context. lint doesn't know,
and can't be made to know, that things other than boolean-returning
relational expressions (such as (a > 5) or (f <= 12)) can meaningfully
be used in a boolean context.

IMNSHO, lint here goes from pedantic to incorrect. Even the earliest
versions of C would gleefully, and conformantly, accept things that
aren't strictly booleans where it imposes a boolean context. For lint to

>
>
>>Ben.c:14:12: Variable strchr used before definition
>> An rvalue is used that may not be initialized to a value on some execution
>> path.
>>Ben.c:17:7: Variable putchar used before definition

>
>
> Erm... boggle.

lint's stupid sometimes.

>
>
>>Ben.c:17:7: Return value (type int) ignored: putchar(p)
>> Result returned by function call is not used.

>
>
> Gosh. Lint really _is_ prehistoric, isn't it?

According to K&R2, putchar() does indeed return an int. I suspect a cast
to void would silence lint, but it's hardly worth it, is it?

[OT]
I use splint, a lint-a-like, myself, and splint gives you the warning,
the explanation, and the argument you can pass to splint to make it shut
up about the damned warning. I usually invoke splint with no flags once,
then with a few to weed out the more egregiously inane whinings.
[/OT]

August Derleth, Jan 5, 2004
8. ### Ben PfaffGuest

August Derleth <> writes:

> lint's stupid sometimes.

lint is stupid to the point of uselessness. As just one example,
at least one variety of lint emits a warning for the following:
long x = 0;
saying that the initializer is not of the proper type.
--
"I'm not here to convince idiots not to be stupid.
They won't listen anyway."
--Dann Corbit

Ben Pfaff, Jan 5, 2004
9. ### Arthur J. O'DwyerGuest

On Mon, 5 Jan 2004, August Derleth wrote:
>
> Richard Bos wrote:
> > Jean-Michel Collard <> wrote:
> >>Ben Pfaff wrote:
> >>
> >>>int main(void){char p[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz.\
> >>> \n",*q="kl BIcNBFr.NKEzjwCIxNJC";int i=sizeof p/2;char *strchr();int putchar(\
> >>>);while(*q){i+=strchr(p,*q++)-p;if(i>=(int)sizeof p)i-=sizeof p-1;putchar(p\
> >>>);}return 0;}
> >>
> >>huh "Just another C hacker"
> >>
> >>Ben.c: (in function main)
> >>Ben.c:9:18: Variable i initialized to type arbitrary unsigned integral type,
> >> expects int: sizeof(p) / 2

> >
> >
> > Correct for this constant value, though.

>
> Eh, lint can't tell that.

It could if it tried hard enough. ;-)

> >>Ben.c:10:9: Function strchr shadows outer declaration
> >> An outer declaration is shadowed by the local declaration.

> >
> > Where, pray, is this "outer declaration" to be found?

>
>
> The old-style implicit declaration of everything returning an int?

Ben's .sig #includes no headers, and "implicit declarations" are
implicit for a reason. They're superseded by "real" declarations.
K&R1 even does this in several places, IIRC. So the bottom line is,
this warning is completely bogus. But my guess is that the guy who
ran lint on the .sig did wrongly #include <string.h> -- how else
would lint be down to line 10 in the source already?

> >>Ben.c:12:10: Test expression for while not boolean, type char: *q
> >> Test expression type is not boolean.

> >
> > Yer_what_?

>
> Here's where lint is a bit too pedantic (well, here's a single instance
> out of possibly thousands ): C acts like it has a boolean type
> sometimes, and it certainly has a boolean context. lint doesn't know,
> and can't be made to know, that things other than boolean-returning
> relational expressions (such as (a > 5) or (f <= 12)) can meaningfully
> be used in a boolean context.
>
> IMNSHO, lint here goes from pedantic to incorrect. Even the earliest
> versions of C would gleefully, and conformantly, accept things that
> aren't strictly booleans where it imposes a boolean context. For lint to

It might be helpful in cases like

if (a=b)

The problems are (1) lint uses the word "boolean" like the programmer
is supposed to know what it means, and which "types" are "boolean"
enough for lint -- but C90 doesn't have boolean types -- and (2) lint
should really know about common idioms like 'if (*q)'. It makes a
large bit of sense to warn about 'if (a+b)' or the like, for the sake
of lint-ness, but lint should know better than to complain in this
case.

> >>Ben.c:17:7: Return value (type int) ignored: putchar(p)
> >> Result returned by function call is not used.

> >
> > Gosh. Lint really _is_ prehistoric, isn't it?

>
> According to K&R2, putchar() does indeed return an int. I suspect a cast
> to void would silence lint, but it's hardly worth it, is it?

Some old code, and some overly-portable code, does use casts to
void. We even get questions about (void)printf here occasionally.
I can only assume there's some way to switch off this warning in
modern lints; it would get really obnoxious if you tried to lint a
big source file.

> [OT]
> I use splint, a lint-a-like, myself, and splint gives you the warning,
> the explanation, and the argument you can pass to splint to make it shut
> up about the damned warning. I usually invoke splint with no flags once,
> then with a few to weed out the more egregiously inane whinings.

Excellent. I wish gcc would do this too, for its warnings. It
seems like a very nice feature.

> [/OT]

-Arthur

Arthur J. O'Dwyer, Jan 5, 2004
10. ### Eric SosmanGuest

Ben Pfaff wrote:
>
> August Derleth <> writes:
>
> > lint's stupid sometimes.

>
> lint is stupid to the point of uselessness. As just one example,
> at least one variety of lint emits a warning for the following:
> long x = 0;
> saying that the initializer is not of the proper type.

I once encountered a *compiler* that complained about

float f = 0.0;

.... because of the potential loss of precision in the
conversion of `double' to `float'. Perhaps the goal of
the compiler vendor was "Get Nothing Right!"

--

Eric Sosman, Jan 5, 2004

Eric Sosman wrote:

> I once encountered a *compiler* that complained about
>
> float f = 0.0;
>
> ... because of the potential loss of precision in the
> conversion of `double' to `float'. Perhaps the goal of
> the compiler vendor was "Get Nothing Right!"

I'm not sure I wholly disagree with the compiler in this case.

Could you explain why you think a warning is so over-the-top here?

Best regards,

Sidney

12. ### Christian BauGuest

In article <btd0ng\$rf6\$>,

> Eric Sosman wrote:
>
> > I once encountered a *compiler* that complained about
> >
> > float f = 0.0;
> >
> > ... because of the potential loss of precision in the
> > conversion of `double' to `float'. Perhaps the goal of
> > the compiler vendor was "Get Nothing Right!"

>
> I'm not sure I wholly disagree with the compiler in this case.
>
> Could you explain why you think a warning is so over-the-top here?

It would be a strange implementation where an assignment of the double
precision number 0.0 to a variable of type float would produce a loss of
precision. Same for 1.0 or 0.5 .

If you have an assignment

float f = <double precision constant>;

then it would be trivial for the compiler to check whether or not
(float)constant == (double)constant or not. Then the compiler can either
give a warning: "Warning: Loss of precision" or be quiet if there is no
loss of precision.

Christian Bau, Jan 6, 2004
13. ### peteGuest

Christian Bau wrote:
>
> In article <btd0ng\$rf6\$>,
>
> > Eric Sosman wrote:
> >
> > > I once encountered a *compiler* that complained about
> > >
> > > float f = 0.0;
> > >
> > > ... because of the potential loss of precision in the
> > > conversion of `double' to `float'. Perhaps the goal of
> > > the compiler vendor was "Get Nothing Right!"

> >
> > I'm not sure I wholly disagree with the compiler in this case.
> >
> > Could you explain why you think a warning is so over-the-top here?

>
> It would be a strange implementation where an assignment of the double
> precision number 0.0 to a variable of type float would produce a loss of
> precision. Same for 1.0 or 0.5 .
>
> If you have an assignment
>
> float f = <double precision constant>;
>
> then it would be trivial for the compiler to check whether or not
> (float)constant == (double)constant or not.
> Then the compiler can either give a warning:
> "Warning: Loss of precision" or be quiet if there is no
> loss of precision.

If the implementation gives warnings based solely on the code,
without regard for implementation defined behavior,
then you'll have less new warnings when you port the code,
assuming that you paid proper heed to the warnings.

--
pete

pete, Jan 6, 2004

Christian Bau wrote:

> In article <btd0ng\$rf6\$>,
>
>>Eric Sosman wrote:
>>
>>
>>> I once encountered a *compiler* that complained about
>>>
>>> float f = 0.0;
>>>
>>>... because of the potential loss of precision in the
>>>conversion of `double' to `float'. Perhaps the goal of
>>>the compiler vendor was "Get Nothing Right!"

>>
>>I'm not sure I wholly disagree with the compiler in this case.
>>
>>Could you explain why you think a warning is so over-the-top here?

>
>
> It would be a strange implementation where an assignment of the double
> precision number 0.0 to a variable of type float would produce a loss of
> precision. Same for 1.0 or 0.5 .

Strange yes, but not impossible, as far as I can tell from the standard.
I don't think there's a requirement that zero be exactly representable
for floats/doubles. Of course, I wholly agree that an FP implementation
would be seriously broken if it couldn't do this.

> If you have an assignment
>
> float f = <double precision constant>;
>
> then it would be trivial for the compiler to check whether or not
> (float)constant == (double)constant or not. Then the compiler can either
> give a warning: "Warning: Loss of precision" or be quiet if there is no
> loss of precision.

Probably the compiler already said "*possible* loss of precision".

Having warnings depend on implementation-defined things is perhaps not a
good idea. To have a rather more interesting example:

float x = 0.1;

We would both, I think, consider the warning to be a good idea at least
on radix-2 FP machines; however, I think it is also not unreasonable to
get a warning on a radix-10 machine (will make porting efforts ever so
much easier).

Best regards, Sidney

15. ### Richard BosGuest

August Derleth <> wrote:

> Richard Bos wrote:
> > Jean-Michel Collard <> wrote:
> >
> >>Ben Pfaff wrote:
> >>
> >>>int main(void){char p[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz.\
> >>> \n",*q="kl BIcNBFr.NKEzjwCIxNJC";int i=sizeof p/2;char *strchr();int putchar(\
> >>>);while(*q){i+=strchr(p,*q++)-p;if(i>=(int)sizeof p)i-=sizeof p-1;putchar(p\
> >>>);}return 0;}
> >>
> >>huh "Just another C hacker"
> >>
> >>Ben.c: (in function main)
> >>Ben.c:9:18: Variable i initialized to type arbitrary unsigned integral type,
> >> expects int: sizeof(p) / 2

> >
> > Correct for this constant value, though.

>
> Eh, lint can't tell that.

Of course it can, for exactly the same reason that I can: in that
context, p is a non-variable-sized array, which has constant size - 56,
to be precise. sizeof p is therefore 56, and sizeof p/2 is 28, and 28
_must_ convert correctly to int.

> >>Ben.c:10:9: Function strchr shadows outer declaration
> >> An outer declaration is shadowed by the local declaration.

> >
> > Where, pray, is this "outer declaration" to be found?

>

There _is_ no header file in that code.

> The old-style implicit declaration of everything returning an int?

That doesn't exist unless the function is called without an explicit
declaration. Which it isn't.

> >>Ben.c:12:10: Test expression for while not boolean, type char: *q
> >> Test expression type is not boolean.

> >
> > Yer_what_?

>
> Here's where lint is a bit too pedantic

No, it's talking out of its hat. The control expression of a while loop
need not be "boolean" at all, whatever lint, in its poor addled
imagination, thinks a "boolean" type is in pre-99 C.

> C acts like it has a boolean type sometimes,

Not unless you're using C99.

> and it certainly has a boolean context.

Yes. And in those contexts, _any_ scalar will suffice - all that is
needed is that it can be tested for being-zero-or-not.

> lint doesn't know, and can't be made to know, that things other than
> boolean-returning relational expressions (such as (a > 5) or (f <= 12))
> can meaningfully be used in a boolean context.

In other words, lint is incorrigibly broken. Such uses are perfectly
correct in C, and flagging them as wrong is simply not correct.

> >>Ben.c:14:12: Variable strchr used before definition
> >> An rvalue is used that may not be initialized to a value on some execution
> >> path.
> >>Ben.c:17:7: Variable putchar used before definition

> >
> > Erm... boggle.

>
> lint's stupid sometimes.

Understatement of the year award granted on January 2nd already.

> >>Ben.c:17:7: Return value (type int) ignored: putchar(p)
> >> Result returned by function call is not used.

> >
> > Gosh. Lint really _is_ prehistoric, isn't it?

>
> According to K&R2, putchar() does indeed return an int.

Yes. And according to the same K&R, there is no need to use the return
value of every single expression. I note, for example, that lint does
not complain about the various assignment statements, whose results are
ignored as well.

> I suspect a cast
> to void would silence lint, but it's hardly worth it, is it?

My point exactly. I haven't seen lint-shutting-up casts for ages, and it
is indeed hardly worth the trouble to deface your code so badly if you
can, with much less effort, throw the bloody dinosaur out the window and
use a proper error-checking compiler.

Richard

Richard Bos, Jan 6, 2004
16. ### CBFalconerGuest

> Eric Sosman wrote:
>
> > I once encountered a *compiler* that complained about
> >
> > float f = 0.0;
> >
> > ... because of the potential loss of precision in the
> > conversion of `double' to `float'. Perhaps the goal of
> > the compiler vendor was "Get Nothing Right!"

>
> I'm not sure I wholly disagree with the compiler in this case.
>
> Could you explain why you think a warning is so over-the-top here?

I think the warning should be emitted. Consider:

#define SOMEVALUE (0)

#define BASEVAL ((SOMEVALUE) / 3.0)

..... globs of code ....

float f, g;

..... further globs ....

f = BASEVAL; /* WARNING TIME */
g = 3 * BASEVAL; /* WARNING TIME */

otherwise the apparently innocent future change of SOMEVALUE may
trigger many confusing warnings.

--
Chuck F () ()
Available for consulting/temporary embedded and systems.

CBFalconer, Jan 6, 2004
17. ### Joe WrightGuest

Christian Bau wrote:
>
> In article <btd0ng\$rf6\$>,
>
> > Eric Sosman wrote:
> >
> > > I once encountered a *compiler* that complained about
> > >
> > > float f = 0.0;
> > >
> > > ... because of the potential loss of precision in the
> > > conversion of `double' to `float'. Perhaps the goal of
> > > the compiler vendor was "Get Nothing Right!"

> >
> > I'm not sure I wholly disagree with the compiler in this case.
> >
> > Could you explain why you think a warning is so over-the-top here?

>
> It would be a strange implementation where an assignment of the double
> precision number 0.0 to a variable of type float would produce a loss of
> precision. Same for 1.0 or 0.5 .
>
> If you have an assignment
>
> float f = <double precision constant>;
>
> then it would be trivial for the compiler to check whether or not
> (float)constant == (double)constant or not. Then the compiler can either
> give a warning: "Warning: Loss of precision" or be quiet if there is no
> loss of precision.

I would doubt very much that the compiler checks that the double value
can be assigned to float without loss of precision. Simply that
assigning double to float might cause it.
--
Joe Wright http://www.jw-wright.com
"Everything should be made as simple as possible, but not simpler."
--- Albert Einstein ---

Joe Wright, Jan 6, 2004
18. ### August DerlethGuest

Richard Bos wrote:

> August Derleth <> wrote:
>
>
>>Richard Bos wrote:
>>
>>>Jean-Michel Collard <> wrote:
>>>
>>>
>>>>Ben Pfaff wrote:
>>>>
>>>>
>>>>>int main(void){char p[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz.\
>>>>>\n",*q="kl BIcNBFr.NKEzjwCIxNJC";int i=sizeof p/2;char *strchr();int putchar(\
>>>>>);while(*q){i+=strchr(p,*q++)-p;if(i>=(int)sizeof p)i-=sizeof p-1;putchar(p\
>>>>>);}return 0;}
>>>>
>>>>huh "Just another C hacker"
>>>>
>>>>Ben.c: (in function main)
>>>>Ben.c:9:18: Variable i initialized to type arbitrary unsigned integral type,
>>>> expects int: sizeof(p) / 2
>>>
>>>Correct for this constant value, though.

>>
>>Eh, lint can't tell that.

>
>
> Of course it can, for exactly the same reason that I can: in that
> context, p is a non-variable-sized array, which has constant size - 56,
> to be precise. sizeof p is therefore 56, and sizeof p/2 is 28, and 28
> _must_ convert correctly to int.

Ah. OK. I might be as dumb as lint sometimes, but at least I can learn.

(In other words, it's bleedingly obvious from the code and if lint can't
pick it up, it's broken. Which seems to be a recurrent theme here.)

>
>
>
>>>>Ben.c:10:9: Function strchr shadows outer declaration
>>>> An outer declaration is shadowed by the local declaration.
>>>
>>>Where, pray, is this "outer declaration" to be found?

>>

>
>
> There _is_ no header file in that code.

I was trying to make lint sound ... not obviously broken.

>
>
>>The old-style implicit declaration of everything returning an int?

>
>
> That doesn't exist unless the function is called without an explicit
> declaration. Which it isn't.

See above.

>
>
>>>>Ben.c:12:10: Test expression for while not boolean, type char: *q
>>>> Test expression type is not boolean.
>>>
>>>Yer_what_?

>>
>>Here's where lint is a bit too pedantic

>
>
> No, it's talking out of its hat. The control expression of a while loop
> need not be "boolean" at all, whatever lint, in its poor addled
> imagination, thinks a "boolean" type is in pre-99 C.

Which is why I found this specific warning absurd. It's confusing
because it's wrong, in other words.

Of course, having a boolean context without having a boolean type is
also a bit odd. C99 fixes this, but it's been a quirk of C for a long time.

>
>
>>C acts like it has a boolean type sometimes,

>
>
> Not unless you're using C99.

Well, I should have phrased better: A context means the value is coerced
implicitly to some type. What type would it be coerced into in a boolean
context? A boolean type, which conveniently does not exist in any C
version earlier than C99.

In other words, see above.

>>lint doesn't know, and can't be made to know, that things other than
>>boolean-returning relational expressions (such as (a > 5) or (f <= 12))
>>can meaningfully be used in a boolean context.

>
>
> In other words, lint is incorrigibly broken. Such uses are perfectly
> correct in C, and flagging them as wrong is simply not correct.

Here I do agree with you now, whereas I wouldn't have when I posted the
original article. lint insisting on things the C Standard doesn't insist
on (*explicitly* doesn't insist on, in fact) is a fault of lint.

>
>
>>>>Ben.c:14:12: Variable strchr used before definition
>>>> An rvalue is used that may not be initialized to a value on some execution
>>>> path.
>>>>Ben.c:17:7: Variable putchar used before definition
>>>
>>>Erm... boggle.

>>
>>lint's stupid sometimes.

>
>
> Understatement of the year award granted on January 2nd already.

I'd like to thank the Academy.

>
>
>>>>Ben.c:17:7: Return value (type int) ignored: putchar(p)
>>>> Result returned by function call is not used.
>>>
>>>Gosh. Lint really _is_ prehistoric, isn't it?

>>
>>According to K&R2, putchar() does indeed return an int.

>
>
> Yes. And according to the same K&R, there is no need to use the return
> value of every single expression. I note, for example, that lint does
> not complain about the various assignment statements, whose results are
> ignored as well.

Heh. Good one ... lint should be complaining left and right about
boolean values being thrown away. Maybe then /everyone/ will decide it's
Not Worth It.

>
>
>>I suspect a cast
>>to void would silence lint, but it's hardly worth it, is it?

>
>
> My point exactly. I haven't seen lint-shutting-up casts for ages, and it
> is indeed hardly worth the trouble to deface your code so badly if you
> can, with much less effort, throw the bloody dinosaur out the window and
> use a proper error-checking compiler.

I concur, even as I pass my code through a lint clone. gcc with -Wall,
-ansi, and -pedantic does wonderful things, but it's just not the same
if I can't decide to ignore warnings instead of acting on them, now is
it?

August Derleth, Jan 7, 2004
19. ### August DerlethGuest

Arthur J. O'Dwyer wrote:

> On Mon, 5 Jan 2004, August Derleth wrote:
>
>>Richard Bos wrote:
>>
>>>Jean-Michel Collard <> wrote:
>>>
>>>>Ben.c:12:10: Test expression for while not boolean, type char: *q
>>>> Test expression type is not boolean.
>>>
>>>Yer_what_?

>>
>>Here's where lint is a bit too pedantic (well, here's a single instance
>>out of possibly thousands ): C acts like it has a boolean type
>>sometimes, and it certainly has a boolean context. lint doesn't know,
>>and can't be made to know, that things other than boolean-returning
>>relational expressions (such as (a > 5) or (f <= 12)) can meaningfully
>>be used in a boolean context.
>>
>>IMNSHO, lint here goes from pedantic to incorrect. Even the earliest
>>versions of C would gleefully, and conformantly, accept things that
>>aren't strictly booleans where it imposes a boolean context. For lint to

>
>
> It might be helpful in cases like
>
> if (a=b)

It would still be wrong, though. See Richard's post for details, but the
upshot is that any scalar value can be coerced via a boolean context
into a form usable by any of the conditional statements. Insisting on a
boolean type, which was quite mythical until C99, is wrong.

What lint should do is shut up about 90% of the cases and correctly warn
about cases like yours with a correct statement, such as `assignment
used where test expected' or some such.

>
> The problems are (1) lint uses the word "boolean" like the programmer
> is supposed to know what it means, and which "types" are "boolean"
> enough for lint -- but C90 doesn't have boolean types -- and (2) lint
> should really know about common idioms like 'if (*q)'. It makes a
> large bit of sense to warn about 'if (a+b)' or the like, for the sake
> of lint-ness, but lint should know better than to complain in this
> case.

In other words, lint should not be broken.

>
>
>
>>>>Ben.c:17:7: Return value (type int) ignored: putchar(p)
>>>> Result returned by function call is not used.
>>>
>>>Gosh. Lint really _is_ prehistoric, isn't it?

>>
>>According to K&R2, putchar() does indeed return an int. I suspect a cast
>>to void would silence lint, but it's hardly worth it, is it?

>
>
> Some old code, and some overly-portable code, does use casts to
> void. We even get questions about (void)printf here occasionally.
> I can only assume there's some way to switch off this warning in
> modern lints; it would get really obnoxious if you tried to lint a
> big source file.

As Richard said, it's not wrong to ignore the value of anything,
including a function call. Otherwise, we'd need to wrap a conditional
statement around every assignment statement.

>
>
>>[OT]
>>I use splint, a lint-a-like, myself, and splint gives you the warning,
>>the explanation, and the argument you can pass to splint to make it shut
>>up about the damned warning. I usually invoke splint with no flags once,
>>then with a few to weed out the more egregiously inane whinings.

>
>
> Excellent. I wish gcc would do this too, for its warnings. It
> seems like a very nice feature.

It's the only way I'll use a lint-like program at all, especially now.

August Derleth, Jan 7, 2004
20. ### August DerlethGuest

Ben Pfaff wrote:

> August Derleth <> writes:
>
>
>>lint's stupid sometimes.

>
>
> lint is stupid to the point of uselessness. As just one example,
> at least one variety of lint emits a warning for the following:
> long x = 0;
> saying that the initializer is not of the proper type.

You could say
long x = 0L;

Or you could stop using lint.

Whichever.

(I'd opt for the second, assuming I have a reasonably good compiler.)

August Derleth, Jan 7, 2004