Lint doesn't catch signed => unsigned arg passing

R

Rahul

Hi,

I have a little program as follows :

=================== STARTS HERE ================
#include <stdio.h>

void f (unsigned long);
int main()
{
short s=0x7FFF; /* == 32767 */

/* == 0x8000 == 32768 (in unsigned) == -32768 (in
signed) */
s++;
/* passing signed short to f(), which expects unsigned long */
f(s);

return (0);
}

void f(unsigned long l)
{
/* note the huge value passed here */
printf ("value is unsigned long = (%lu), hexadecimal =
(0x%lX)\n",
l, l);
}

=================== ENDS HERE ================

(FYI : I am using Solaris Workshop 6.2 on Solaris 8).

Running the above program (compiled with -xarch=v9 option -- for
64-bit), gives me following result (which I guess, expected) :
--------
value is unsigned long = (18446744073709518848), hexadecimal =
(0xFFFFFFFFFFFF8000)
--------

If I run lint to catch such mismatch datatype, I cann't see any
complains from lint :-( ...

lint -errchk=%all a.c (note, %all includes sizematch see
http://docs.sun.com/db/doc/805-4952/6j4mdcehi?a=view), gives me
following output :
-------
function returns value which is always ignored
printf

declared global, could be static
f a.c(19)
-------

My question is : Is there any way that I can catch such wrong
mismatchs in datatypes (-errchk=sizematch does catch if I pass
unsigned to signed, but not the other way)?

Thanks a lot!
RMD.
 
J

Jack Klein

Hi,

I have a little program as follows :

=================== STARTS HERE ================
#include <stdio.h>

void f (unsigned long);
int main()
{
short s=0x7FFF; /* == 32767 */

/* == 0x8000 == 32768 (in unsigned) == -32768 (in
signed) */
s++;

Assuming that short is 16 bits, your program generates undefined
behavior at the line above. I am surprised your lint doesn't catch
that.
/* passing signed short to f(), which expects unsigned long */
f(s);

There is no problem with passing a signed short to a function that
takes an unsigned long parameter. There is an automatic promotion,
and the conversion cannot overflow even if the value is negative.
return (0);
}

void f(unsigned long l)
{
/* note the huge value passed here */
printf ("value is unsigned long = (%lu), hexadecimal =
(0x%lX)\n",
l, l);
}

=================== ENDS HERE ================

(FYI : I am using Solaris Workshop 6.2 on Solaris 8).

Running the above program (compiled with -xarch=v9 option -- for
64-bit), gives me following result (which I guess, expected) :
--------
value is unsigned long = (18446744073709518848), hexadecimal =
(0xFFFFFFFFFFFF8000)
--------

If I run lint to catch such mismatch datatype, I cann't see any
complains from lint :-( ...

lint -errchk=%all a.c (note, %all includes sizematch see
http://docs.sun.com/db/doc/805-4952/6j4mdcehi?a=view), gives me
following output :
-------
function returns value which is always ignored
printf

declared global, could be static
f a.c(19)
-------

My question is : Is there any way that I can catch such wrong
mismatchs in datatypes (-errchk=sizematch does catch if I pass
unsigned to signed, but not the other way)?

Thanks a lot!
RMD.

As to why your version of lint does not do what you want, you had
better check with your lint vendor or try a Solaris group.

Lint is not defined or specified by the C language standard, making it
off-topic here. Furthermore, there is not one lint, but many, and
only the vendors decide how each one operates.
 
P

Peter Shaggy Haywood

Groovy hepcat Rahul was jivin' on 23 Feb 2004 12:42:40 -0800 in
comp.lang.c.
Lint doesn't catch signed => unsigned arg passing's a cool scene! Dig
it!
#include <stdio.h>

void f (unsigned long);
int main()
{
short s=0x7FFF; /* == 32767 */

/* == 0x8000 == 32768 (in unsigned) == -32768 (in
signed) */
s++;

You may have just invoked undefined behaviour by overflowing a
signed integral type. If SHRT_MAX is 32767, then that is the case. Of
course, if it is higher, then incrementing s is perfectly fine, and
has a positive result.
In the real world, compilers will typically just wrap the value
around to a negative one if it overflows.
/* passing signed short to f(), which expects unsigned long */
f(s);

Converting a signed number to an unsigned one is well defined. If
the value is positive and fits in the type being converted to, it is
unchanged. Otherwise the value is modified by adding or subtracting
the maximum value of the type being converted to plus one.
So, assuming that on some hypothetical implementation s wraps in the
above lines of code to -32768, and ULONG_MAX is 4294967295, then
function f() recieves the value -32768 + 4294967295 + 1 or
4294934528.
return (0);
}

void f(unsigned long l)
{
/* note the huge value passed here */
printf ("value is unsigned long = (%lu), hexadecimal =
(0x%lX)\n",
l, l);
}

=================== ENDS HERE ================

(FYI : I am using Solaris Workshop 6.2 on Solaris 8).

Running the above program (compiled with -xarch=v9 option -- for
64-bit), gives me following result (which I guess, expected) :

This is to be expected if a) s is being wrapped to a negative
number, and b) unsigned long is a 64 bit type (with no padding bits).
If I run lint to catch such mismatch datatype, I cann't see any
complains from lint :-( ...

Nor should you. This is perfectly legal.
lint -errchk=%all a.c (note, %all includes sizematch see
http://docs.sun.com/db/doc/805-4952/6j4mdcehi?a=view), gives me
following output :
-------
function returns value which is always ignored
printf

declared global, could be static
f a.c(19)
-------

My question is : Is there any way that I can catch such wrong
mismatchs in datatypes (-errchk=sizematch does catch if I pass
unsigned to signed, but not the other way)?

Yes. Open up your eyes and fire up a few synapses, and get your
brain working on it.

--

Dig the even newer still, yet more improved, sig!

http://alphalink.com.au/~phaywood/
"Ain't I'm a dog?" - Ronny Self, Ain't I'm a Dog, written by G. Sherry & W. Walker.
I know it's not "technically correct" English; but since when was rock & roll "technically correct"?
 

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,769
Messages
2,569,581
Members
45,056
Latest member
GlycogenSupporthealth

Latest Threads

Top