rwwetmore@grand.waterloo.edu (Ross Wetmore) (07/19/88)
>: (int)n = (char *)p - (char *)q; >: This is perfectly valid 'C' > Read about casting lvalues again. >: and will never to my knowledge be picked >:up by any lint program. Right this was never intended to be a cast :-). While I might have gotten away with 'int n = (char *)p - (char *)q;' what I really should have done is made all the definitions explicitly, and avoided trying to squish things down to a single line or at least been a little more careful to double check what I had written as opposed to thought. My apologies for the confusion this may have caused. Moral: always use lint and spell on mail messages before posting :-) >: The fact that NULL, defined as the integer constant 0, is explicitly >:defined to be a valid null pointer on assignment (but not generally, >:which is what caused the original problem) only reinforces the linkage. >No, (char *) NULL is the null pointer. 0 is 0. If you don't believe >that, I bet a lot of your 68000-based code crashes for no apparent >reason. From the first line on pg 97 of K&R ... #define NULL 0 /* pointer value for error report */ QED. Your comment on 68K code crashing only reinforces my point. >When talking about portable code, you had better >be planning to recognize the difference between a pointer and an >integer or you had better plan on spending late nights wondering >why your code keeps falling over. It's that simple --- K&R say a >pointer is a pointer and an integer is an integer and they may be of >different size. Live with it. >-david- K&R also says that the result of pointer arithmetic is an int. And any implementation of standard C functions I have ever seen has things like strlen(), sizeof() ... returning an int-sized value. Note that lseek() which refers to disk addresses returns a long (ie the largest possible integer size on the machine). While pointers and ints are declared to be of different sizes, somehow the size of an int and a pointer are still linked by such constructs. This means that pointer code which runs fine on a 32-32 machine fails inexplicably on a 32-16 machine where the only diifference in the machines is changing the size of an int from 32 to 16. >So, if my ints are 32 bits and my pointers 64, I am not running K&R >C? Nonsense! No, I never said that. The correct conclusion was what my original posting gave in counterpoint to the previous claim that an architecture was broken if such code failed. The conclusion was that one could not fault the architecture or compiler, and if anything was broken it was the language specifications that permitted or dictated such inconsistencies. In fact the Intel architecture commented on enforces strict conformance with K&R in the hardware. I like C just fine, and prefer it to many other languages I use, but this still does not mean I have to be bashful about its shortcomings either those explictly recorded in K&R or those carefully not recorded there. I still think C works best on machines where pointers and ints are the same size :-) Ross W. Wetmore | rwwetmore@water.NetNorth University of Waterloo | rwwetmore@math.Uwaterloo.ca Waterloo, Ontario N2L 3G1 | {uunet, ubc-vision, utcsri} (519) 885-1211 ext 3491 | !watmath!rwwetmore
chris@mimsy.UUCP (Chris Torek) (07/23/88)
In article <19964@watmath.waterloo.edu> rwwetmore@grand.waterloo.edu (Ross Wetmore) writes: >>: The fact that NULL, defined as the integer constant 0, is explicitly >>:defined to be a valid null pointer on assignment (but not generally, >>:which is what caused the original problem) only reinforces the linkage. [between pointers and integers] It may have been a design mistake, but it is not a fatal one. [someone else, name forgotten:] >>No, (char *) NULL is the null pointer. There is no `the null pointer': there are an infinite variety of nil pointers. (char *)NULL is `the nil pointer to char', and nothing else. There are many machines on which `char *' pointers have more bits, or have bits in different places, than other pointers; there is at least one machine on which pointers to functions are nine times longer than pointers to data. From this it is easy to see why the proper cast is required: any other cast may give you the wrong number of bits, or the right number of bits but in the wrong order. > K&R also says that the result of pointer arithmetic is an int. Rather, that the result of pointer *subtraction* is an int. In the draft proposed American National Standards C Standard X3J11, the result is defined as an object of type `ptrdiff_t', which is simply a signed integral type (and hence may be `long' rather than `int'). This, along with `size_t', removes the existing restriction that any single object may not be larger than an int-worth. > While pointers and ints are declared to be of different sizes, somehow >the size of an int and a pointer are still linked by such constructs. >This means that pointer code which runs fine on a 32-32 machine fails >inexplicably on a 32-16 machine where the only diifference in the >machines is changing the size of an int from 32 to 16. Only if (assuming a byte-addressed machine) objects on the 32-16 machine are allowed to span more than 65536 bytes, and only under K&R rules, not under the dpANS rules. Note that so-called `huge model' compilers for the IBM PC use rules closer to those in the dpANS (so that they will be useful). >I still think C works best on machines where pointers and ints >are the same size :-) Certainly lazily-written C code works best on machines where this is true (and where pointers are untagged and everything is byte-addressed). -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163) Domain: chris@mimsy.umd.edu Path: uunet!mimsy!chris
allbery@ncoast.UUCP (Brandon S. Allbery) (08/02/88)
As quoted from <19964@watmath.waterloo.edu> by rwwetmore@grand.waterloo.edu (Ross Wetmore): +--------------- | >: The fact that NULL, defined as the integer constant 0, is explicitly | >:defined to be a valid null pointer on assignment (but not generally, | >:which is what caused the original problem) only reinforces the linkage. | >No, (char *) NULL is the null pointer. 0 is 0. If you don't believe | >that, I bet a lot of your 68000-based code crashes for no apparent | >reason. | | From the first line on pg 97 of K&R ... | | #define NULL 0 /* pointer value for error report */ | | QED. Your comment on 68K code crashing only reinforces my point. +--------------- And in the middle of page 98, discussing the same code... "Any pointer may be meaningfully compared for equality or inequality with NULL. But all bets are off if you do arithmetic or comparisons with pointers pointing to different arrays. If you're lucky, you'll get obvious nonsense on all machines. If you're unlucky, your code will work on one machine but collapse mysteriously on another." Sounds like K&R disagree with you.... +--------------- | K&R also says that the result of pointer arithmetic is an int. And +--------------- Where, pray tell? +--------------- | any implementation of standard C functions I have ever seen has things | like strlen(), sizeof() ... returning an int-sized value. Note that +--------------- A bad habit, it should properly be something like memsize_t which on many BUT NOT ALL machines may be (int). (Compare large-model 80286 where strlen() may conceivably have to return a (long), and it will break! because of the cavalier attitude toward pointer/integer conversion held by many programmers.) Before you start in about how it's standard so it must be right, tell me how many Berkeley programs assume that *((char *) 0) == '\0' instead of following the rule that that address is supposed to be outside the process's address space? +--------------- | fault the architecture or compiler, and if anything was broken it was | the language specifications that permitted or dictated such | inconsistencies. In fact the Intel architecture commented on enforces | strict conformance with K&R in the hardware. +--------------- First you say the language specs are broken, then you say they are correct? Or are you trying to pass the old "all the world's a VAX" argument to us under new guise? I refuse to believe that C is *supposed* to be Vax-only, I prefer to believe K&R. +--------------- | there. I still think C works best on machines where pointers and ints | are the same size :-) +--------------- I think C works best when you use it properly. Funny, but when you *do* do so, your programs will run anywhere. Please note that without some means of getting the proper sizes of things, the compiler *cannot* make the right decisions -- it can't read your mind to find out that strlen() takes a (char *), it has to have ANSI prototypes added so you can tell it about "memsize_t strlen(const char *)". --And please note the type I used, having it return (int) is identical to all the other pointer/integer problems we've been discussing. This *is* a short- coming, but if you cast things to work around it things work fine. I use C with the assumption that that is the way things are supposed to work; given the possibility of "varargs" functions, not even ANSI prototyping will solve all your problems. Consider `execl("/bin/foo", "foo", "bar", 0)' under 80286 large model. You can't describe it under ANSI prototypes -- or any other prototyping system unless you put so many constraints on function arguments that e.g. printf() won't work any more. And it will assuredly drop core. C *requires* that you specify the argument types because it allows you to have functions change their expected argument lists on the fly (compare printf again). Moreover, done correctly according to the language rules varargs *does* seem to work on all systems -- because of this wonderful generality. ++Brandon -- Brandon S. Allbery, uunet!marque!ncoast!allbery DELPHI: ALLBERY For comp.sources.misc send mail to ncoast!sources-misc