[net.lang.c] Uses of \"short\" ?

gwyn@BRL.ARPA (VLD/VMB) (10/12/85)

I don't see what "trapping integer overflows" has to do with this
topic.  Using the wrong size integer can fail in other ways.

There is absolutely no use for types "int8", "int16", and "int32"
since the shortest C types that fit them can always be used:
"signed char", "short", and "long".  The only possible merit to
introducing types like this would be to represent some oddball
size such as "int24", which might be a "short" on a 24-bit machine
and a "long" on 16- or 32-bit machines.  In the VERY RARE case
that you have to minimize storage on a 24-bit machine, you might
well define "int24" accordingly and use it JUST for the large
storage-consuming data type, with an #ifdef to define it right
for your specific machine and as "long" otherwise.

Similarly, "int60" will only be used where C guarantees non-
portability.  If for some reason you really have to exceed 32
bits in an integer data type and cannot afford the overhead of
doing it portably, then certainly defining "int60" (ONLY for
your specific machine) will cause the portability problem to
become very visible when the code finally is ported, which is
undoubtedly better than having the code fail mysteriously.

General use of unnecessary names like "int8", "int16", and "int32"
just makes it harder for others to maintain your code without
contributing anything whatever to the portability of the code.

preece@ccvaxa.UUCP (10/15/85)

> /* Written  2:45 am  Oct 12, 1985 by gwyn@BRL.ARPA in ccvaxa:net.lang.c
> */ There is absolutely no use for types "int8", "int16", and "int32"
> since the shortest C types that fit them can always be used: "signed
> char", "short", and "long".
----------
At risk of belaboring the obvious, the point is that "int8",
"int16", and "int32" mean the same thing everywhere, while
"unsigned char", "short", and "long" are machine dependent.
If one carefully uses short and long so that code compiles
efficiently both on my UTX machine and Guy Harris's PDP-11s,
it STILL may break on another machine where short and long
are NOT the usual 16 and 32 bits.  That's the whole point.

If you're going to spend much energy on generating portable
code you MUST use typedefs with funny names that actually have
specific, machine independent definitions.

-- 
scott preece
gould/csd - urbana
ihnp4!uiucdcs!ccvaxa!preece

berger@datacube.UUCP (10/16/85)

The main use would be when you create structures that describe the
layout of registers in hardware. In otherwords, when you are writing
a driver or something you might say:

struct deviceRegs {
	int8 csr0;
	int8 csr1;
	int16 dataport;
};

register struct deviceRegs *p = (struct deviceRegs *)0x40000;

	p->csr0 = 0xff;
		etc.

You want each structure element to be a particular size so you can access
particular 8 bit bytes or 16 bit words.  This does not protect you from
byte swapping and I suspect some compilers might throw in hidden alignments,
but in general it works and looks nice.

			Bob Berger 

Datacube Inc. 4 Dearborn Rd. Peabody, Ma 01960 	617-535-6644
	
ihnp4!datacube!berger
decvax!cca!mirror!datacube!berger
{mit-eddie,cyb0vax}!mirror!datacube!berger

mikeb@inset.UUCP (Mike Banahan) (10/19/85)

Uh? I thought that to do stuff like

	struct devregs{
		int8 csr0;
		int8 csr1;
		int16 foobar;
	};
you would use bitfields. The whole thing is intrinsically nonportable,
since you're talking to a bit of hardware anyhow, so the noportability
of bitfields is no sweat. Or did I miss something?
-- 
Mike Banahan, Technical Director, The Instruction Set Ltd.
mcvax!ukc!inset!mikeb

gwyn@BRL.ARPA (VLD/VMB) (11/11/85)

You ask for a reference for developing good portable code.
Well, "good" is hard, but "portable" is rather simple.
Just stick to what the C Reference Manual says about
the language, and refuse to use whatever you "know"
about your particular system that is not guaranteed
by the language definition.  That would eliminate most
of the usual portability problems found in C code.

Designing your application to be insensitive to the
details of the operating environment is harder.  You
should, as a minimum, identify such dependencies and
isolate them inside per-environment modules that
implement a common "portable" interface to the facilities.
(The STDIO library is an example of such a package;
the "curses" library is another.)  That way only a
small, known piece of your application requires
adaptation when you port the code to a new environment.

Beyond that, you need to wait for Laura's book..

gwyn@BRL.ARPA (VLD/VMB) (11/15/85)

Your note reminded me of something I wanted to comment on.
I have observed a lot of C code that tries converting back
and forth between data types (using type casts) with wild
abandon.  This is symptomatic of a program out of control.
Using appropriate data types in a straight-forward fashion
results in code containing very few type casts.  The main
uses I have for type casts fall into a few categories:

	(void) to discard the return value of a function;
	this should be not be done without thinking about
	the appropriateness of ignoring the return value.
	I do this mainly for fprintf(stderr,...), since
	usually I can't think of anything better to do if
	that function call fails.

	Casting the returned value from malloc() (also the
	argument to free()).  This should be obvious.

	Forcing a short or an int to become a long, as in
		i = j * (long)k / l;
	to avoid numeric overflow.

	Truncating a floating-point quantity to its integer
	part (warning! not the same as the floor() function).

	Passing a NULL pointer argument to a function.

	Documenting a coercion that will occur anyhow, as
	in passing a (char) as a function argument or in
	certain assignments, when it is important to
	realize that this is happening.

There are some other instances where casts are useful, but
they should be used sparingly and not as a substitute for
declaring data types properly.

ado@elsie.UUCP (Arthur David Olson) (11/15/85)

> . . .The main uses I have for type casts fall into a few categories:
>
>   (void) to discard the return value of a function. . .
>
>   Casting the returned value from malloc() (also the argument to free()). . .
> 
>   Forcing a short or an int to become a long. . .to avoid numeric overflow.
> 
>   Truncating a floating-point quantity to its integer part. . .
> 
>   Passing a NULL pointer argument to a function.
> 
>   Documenting a coercion that will occur anyhow. . .

Be sure to add:

    Casting the first argument to fread and fwrite.
--
C is a Jack Benny/Mel Blanc trademark.
--
	UUCP: ..decvax!seismo!elsie!ado    ARPA: elsie!ado@seismo.ARPA
	DEC, VAX and Elsie are Digital Equipment and Borden trademarks