Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!mnetor!seismo!husc6!mit-eddie!genrad!decvax!ucbvax!jade!eris!mwm From: mwm@eris.BERKELEY.EDU (Mike (My watch has windows) Meyer) Newsgroups: comp.lang.c Subject: Re: Standard int sizes Message-ID: <3175@jade.BERKELEY.EDU> Date: Wed, 15-Apr-87 08:43:07 EST Article-I.D.: jade.3175 Posted: Wed Apr 15 08:43:07 1987 Date-Received: Sun, 19-Apr-87 05:26:18 EST References: <6759@brl-adm.ARPA> <230@ems.UUCP> <170@vianet.UUCP> <832@viper.UUCP> <981@copper.TEK.COM> Sender: usenet@jade.BERKELEY.EDU Reply-To: mwm@eris.BERKELEY.EDU (Mike (My watch has windows) Meyer) Organization: Missionaria Phonibalonica Lines: 152 In article <981@copper.TEK.COM> stevesu@copper.TEK.COM (Steve Summit) writes: >Slavishly coding an entire program with things like int16 and >int32 does nothing to improve the overall portability, >readability, or efficiency of the program. Quite correct. This just means that these creatures, like any other creature, can be abused as well as used. Most of the rest of your article, discussing abstract data types and the like is also quite correct. But you missed a few points that make such creatures nice to have. For instance, you said: >Say what you mean! You probably don't need a type that can hold >a 32-bit value just because it can hold a 32-bit value. You >probably have a more abstract quantity in mind, like "distance" >or "temperature" or "furlongs per fortnight." Then you can say > > typedef long int Distance; /* distance in millimeters */ > typedef int Temperature; /* temperatures in degrees C */ > typedef char FurlongsPerFortnight; /* velocity ad absurdium */ Very nice. And probably sufficient over 90% of the time. But not complete. To take an example from something I did this weekend, I had (more accurately, should have had) the following: /* * We're counting objects of size 8 or larger in something of size 16Meg. * This can be bigger than 64K, so use a long. */ typedef long chunk_count ; Whereas I'd really like to say: /* * We're counting objects of size 2^3 or larger in something of size 2^24. * Minimum count is zero, maximum is 2^21, so use a uint21. */ typedef uint21 chunk_count ; In this case, I have a hard upper bound, not some "a short's to small" size. If this might run on strange hardware (say a harris/6), the above could be a major win. >To consider a previously-posted example (so artificial it should >probably be ignored), if for some reason you really need a 16-bit, >signed value, say > > typedef long int funnyvalue; /* 16 bits PLUS sign */ > >If that ends up being unacceptably inefficient on your >hypothetical Queer Machine for C, where longs are 36 bits and >slow, you can say > > #ifndef QMC > typedef long int funnyvalue; /* 16 bits PLUS sign */ > #else > typedef int funnyvalue; /* ints are 18 bits on QM/C */ > #endif Ugh. Wouldn't it be a _lot_ nicer to say: #include typedef int16 funny_value ; >If what you want to do is stamp your foot and demand 16 (or 32 or >27 or whatever) bits, and let somebody else be totally >responsible for figuring out how to do it, then use PL/I or ADA. No, I don't want to force someone else to figure out how to do it. I want a nice, portable way of handling the cases where I know exactly how big something needs to be. That's the idea behind the int_sizes.h include, it gives me that. Wanna see how easy that is to do? Here's a version that will be correct on all machines with 8 bit chars, 16 bit shorts and 32 bit longs (of which there are lots...): /* Signed ints */ typedef signed char int1, int2, int3, int4, int5, int6, int7; typedef short int int8, int9, int10, int11, int12, int13, int14, int15; typedef long int int16, int17, int18, int19, int20, int21, int22, int23, int24, int25, int26, int27, int28, int29, int30, int31; /* Unsigned ints */ typedef unsigned char uint1, uint2, uint3, uint4, uint5, uint6, uint7, uint8; typedef unsigned short uint9, uint10, uint11, uint12, uint13, uint14, uint15, uint16; typedef unsigned long uint17, uint18, uint19, uint20, uint21, uint22, uint23, uint24, uint25, uint26, uint27, uint28, uint29, uint30, uint31, uint32; Gee, that was easy. Why don't I do one for the QM/C (which does twos complement), just for grins? We'll assume that the QM/C is word addressed, so a char is also a short. /* Signed ints */ typedef short int int1, int2, int3, int4, int5, int6, int7, int8, int9, int10, int11, int12, int13, int14, int15, int16, int17; typedef long int int18, int19, int20, int21, int22, int23, int24, int25, int26, int27, int28, int29, int30, int31, int32, int33, int34, int35; /* Unsigned ints */ typedef unsigned short uint1, uint2, uint3, uint4, uint5, uint6, uint7, uint8, uint9, uint10, uint11, uint12, uint13, uint14, uint15, uint16, uint17, uint18; typedef unsigned long uint19, uint20, uint21, uint22, uint23, uint24, uint25, uint26, uint27, uint28, uint29, uint30, uint31, uint32, uint33, uint34, uint35, uint36; Now, you may well ask (and it's well you do, as that gives me a chance to point out another advantage :-), what happens if some person on the QM/C decides they need a 33 bit signed quantity for some reason, and so quite correctly codes: /* * This type need this many bits because blah blah blah. */ typedef int33 my_funny_type ; Then later, some poor, unsuspecting programmer comes along and has to port this to something normal, like an 8086? Well, they'll drop it into the compiler, which will blow up in their faces because there _isn't_ a type int33. With luck, they'll type C-x `, GNU emacs will dump them on the above typedef, and they can then read the comments and decide how to handle it. Ah, but what if the programmer didn't bother putting in a comment? Then you can chase down the type"my_funny_value", and figure out what needs to be done. On the other hand, if the person blithly coded "long" on the QM/C because there wasn't an int_sizes.h, then the code compiles. With luck, it'll die in the test suite or some other innocent point. More likely, there'll be no test suite, and somebody will start getting ludicrous answers out of the program. Worse yet, they'll get wrong but not ludicrous answers, and assume that the answers are right. In summary: most of the time, you really don't need the ability to specify sizes to the bit. Every once in a while, you do. An include file that gives the smallest size for each flavor on the machine is about 5 minutes work with a good text editor. It requires no changes to the compiler. If used incorrectly, it won't hurt much (about the most that can be said for any feature). If used correctly, it allows portable code to be efficient on machines with odd-ball word sizes, and allows the compiler to catch assumptions about word sizes that deviate from the minimum.