mwm@cuuxb.UUCP (01/26/87)
My apologies to dmr, my only true justification for the code in the previous article (namely: f() { int a,b,c; b(&a); } b( p ) struct { a , b , c } *p; { /* use p->b, p->c to get at b and c in f() */ } ) is that the majority of c compilers will accept it. As to its effect being undefined, this is correct, but it will work on many machines (although reversing the order of the declarations of a b and c in f() may be neccesary). My attribution of similar code to dmr was also in error, I find that when I refer to the code I was thinking of, it is more of the style: struct { a, b, c, } f( p ) int *p; { /* use of p->a, p->b, etc. */ } (examples are found in most of the v6 kernel routines that take inode pointers as arguments -- of course this is also archaic c, used before the book was written.) which is simple pointer punning, which is much more palatable. My originally inteded point, however, that the present compilers will accept code like my first example, and that it can, with appropriate cajolery, be made to work, means that indiscriminant movmement of variables to registers potentially breaks code. Some of you have already stated that you consider this unimportant, as such code should never have been written to begin with, and *should* break. Personaly I agree, but a person who has "inherited" such a program from someone else might disagree when he has to find and fix the bug... I was also probably thinking of similar discussions I have had in the past about putting external variables into registers, which doesn't work because you need to check not just the current routine, but also every other routine in the program, before the decision whether or not the address-of operator can be used can be made. scorched and blistered, -- Marc Mengel ...!ihnp4!cuuxb!mwm