andrew@teletron.UUCP (Andrew Scott) (09/15/87)
I am curious as to why pointer casts behave the way they do. Specifically, casting from a pointer to one type to a pointer to another type may cause address exceptions if the alignment requirements of the two types differ (as described in section 14.4 of K&R). Thus, it is the programmer's responsibility to insure that the pointers involved in such expressions point to valid addresses after the cast. Why is this the case? It seems to me that the cast should produce code which aligns the pointer to a proper alignment boundary if necessary. The compiler should hide such a machine dependant thing from the programmer. What is the purpose of such a cast (other than to make lint happy) if not to convert a valid data value of one type to a valid data type of another? Does anybody have any answers? Andrew
guy%gorodish@Sun.COM (Guy Harris) (09/20/87)
> Why is this the case? It seems to me that the cast should produce code > which aligns the pointer to a proper alignment boundary if necessary. Except that this would mean that the pointer in question, after having been "rounded up" or "rounded down" so to speak, would no longer point to the location you thought it would point to. > The compiler should hide such a machine dependant thing from the programmer. So? The compiler can't hide all the nasty details of the outside world from programmers. If you want to write machine-independent code, don't cast pointers. If you want to write machine-dependent code, go ahead, but take responsibility for the consequences; be prepared for this code not to work on machines other than the ones you wrote it for. > What is the purpose of such a cast (other than to make lint happy) if not > to convert a valid data value of one type to a valid data type of another? OK, on a byte-addressible machine with 4-byte "int"s that disallows off-boundary references to quantities longer than one byte (such as the machine on which this message is being typed), how would you convert the value of a "char *" containing the bit pattern "0xfeffffc1" into an "int *"? Leave it alone? That would make it an invalid pointer. Use the value of an "int *" containing the bit pattern "0xfeffffc0" or "0xfeffffc4"? That would mean you wouldn't be pointing to "the 'int' at location 0xfeffffc1", i.e. the 4-byte quantity with one end at location "0xfeffffc1" and the other end at location "0xfeffffc5". If the pointer in question is guaranteed not to be misaligned (e.g., pointers returned by "malloc"), it would be wasteful to adjust the pointer. If it is not guaranteed to be misaligned, you have the two choices above, neither of which gets you what you want. As such, compilers generally take the "path of least resistance" and make portable or reasonable-though-nonportable code work, at the expense of making more *outr\'e* types of code not work. Guy Harris {ihnp4, decvax, seismo, decwrl, ...}!sun!guy guy@sun.com
gwyn@brl-smoke.ARPA (Doug Gwyn ) (09/21/87)
In article <100@teletron.UUCP> andrew@teletron.UUCP (Andrew Scott) writes: >... Thus, it is the programmer's >responsibility to insure that the pointers involved in such expressions >point to valid addresses after the cast. >Why is this the case? It seems to me that the cast should produce code >which aligns the pointer to a proper alignment boundary if necessary. The compiler cannot tell how you intend to eventually use the converted pointer. It is exceeding unlikely that automatic rounding of a pointer's address value (whatever that may mean) to some other alignment would result in anything useful; if the pointer were not already properly aligned (as malloc()'s return values are), then "adjusting" its value would result in a new pointer that no longer pointed to sane data. Generally, you should not attempt to play tricks with pointer casts (other than on the result of malloc() and the argument to free()) until you're quite familiar with C. If you declare types correctly, such casts are seldom necessary, and they're almost always associated with non-portable code. (There are a few exceptions.)
andrew@teletron.UUCP (Andrew Scott) (09/21/87)
In article <6449@brl-smoke.ARPA>, gwyn@brl-smoke.ARPA (Doug Gwyn ) writes: > > Generally, you should not attempt to play tricks with pointer casts > (other than on the result of malloc() and the argument to free()) > until you're quite familiar with C. If you declare types correctly, > such casts are seldom necessary, and they're almost always associated > with non-portable code. (There are a few exceptions.) Actually, this whole question came up because I am writing a form of malloc() for a target operating system, obviously unportable. I ended up performing the necessary alignment myself, but I was just curious as to why pointer casts exist if they basically do nothing. On a (sort of) related question, one I am sure has been brought up before, is there a way to make lint shut up about "possible pointer alignment" problems when one is sure there are no problems (such as casting the return value of malloc() )? Our documentation does not mention any kind of comment (like /* VARARGS */) which would do the trick. Andrew
franka@mmintl.UUCP (Frank Adams) (09/22/87)
In article <100@teletron.UUCP> andrew@teletron.UUCP (Andrew Scott) writes: >I am curious as to why ... casting from a pointer to one type to a pointer >to another type may cause address exceptions if the alignment requirements >of the two types differ (as described in section 14.4 of K&R). ... It >seems to me that the cast should produce code which aligns the pointer to a >proper alignment boundary if necessary. ... What is the purpose of such a >cast (other than to make lint happy) if not to convert a valid data value of >one type to a valid data type of another? The reason is speed. Generally speaking, good programming practice (when it produces such casts at all, which is not all that often) will always produce a valid pointer in such cases. The vast majority of such casts in good code fall into one of two categories: 1) Casting the result of a malloc (or other allocation primitive) to the type of the data being allocated. In this case, proper alignment is guaranteed by malloc, so fix up code is a waste of time. 2) A pointer is cast to a less restricted type (for example, "int *" to "char *"), and then back again. On the cast back, there can be no alignment problem, since the value already was in the appropriate form. Furthermore, what is the point of aligning the cast pointer to the proper boundary? This is almost always wrong, and it hides the error from the programmer. (Lots of machines will hide this error anyhow, but there is no point in penalizing the programmers on better architectures.) -- Frank Adams ihnp4!philabs!pwa-b!mmintl!franka Ashton-Tate 52 Oakland Ave North E. Hartford, CT 06108
gwyn@brl-smoke.ARPA (Doug Gwyn ) (09/25/87)
In article <101@teletron.UUCP> andrew@teletron.UUCP (Andrew Scott) writes: >is there a way to make lint shut up about "possible pointer alignment" No, not without modifying "lint".
throopw@xyzzy.UUCP (Wayne A. Throop) (09/28/87)
> andrew@teletron.UUCP (Andrew Scott) > I was just curious as to why > pointer casts exist if they basically do nothing. IF pointer casts did basically did nothing, THEN their existance might well be pointless. But they *DO* do something. They create a new value which has the format of a pointer of the cast type. On many machines, where all pointers have the same format, this does nothing. But the conceptual operation is still important, because there are machines where something must be done in such cases, such as casting from a short pointer type to a long one in some PC C implementations, or from character-granular pointer types to word-granular pointer types in some word-oriented machines. The cast operation doesn't guarantee the *alignment* of the result, but it does guarantee the *format* if the alignment already makes sense. -- Inigo hated it there. Everybody was so dangerous, big, mean and muscular, and so what if he was the greatest fencer in the world, who'd know it to look at him? He looked like a skinny Spanish guy it might be fun to rob. You couldn't walk around with a sign saying "Be careful, this is the greatest fencer since the death of the Wizard of Corsica. Do not burgle." --- From The Princess Bride by William Goldman -- Wayne Throop <the-known-world>!mcnc!rti!xyzzy!throopw