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