Xref: utzoo comp.lang.c:12359 comp.arch:6260 Path: utzoo!attcan!uunet!husc6!mailrus!iuvax!pur-ee!hankd From: hankd@pur-ee.UUCP (Hank Dietz) Newsgroups: comp.lang.c,comp.arch Subject: Re: Explanation, please! Summary: A correction & a few comments. Message-ID: <9087@pur-ee.UUCP> Date: 5 Sep 88 16:57:18 GMT References: <638@paris.ics.uci.edu> <566@pcrat.UUCP> Organization: Purdue University Engineering Computer Network Lines: 54 Relative to my article <9064@pur-ee.UUCP> giving a struct-based hack for doing block copy and to all followups thereof.... Correction: I hereby appologize for having ommitted a (:-) and hence having made it sound like I didn't know why the VAX compiler didn't want to use a cast pointer as the operand of ++. I do know (and I knew even before a dozen of you reminded me :-), I just think it should be allowed in such cases; i.e., be implementation dependent rather than illegal. Anyway, the union-based fix given by Jabir is certainly a good way to do it (once you fix his typedef to make t512 and t256 pointers to structs, rather than structs). Comments: As I noted in the original posting, the use of a structure-hack block copy is subject to alignment problems -- if the target machine has alignment constraints. There are three additional notes on this: 1. Both the source AND destination pointers may need to be aligned, which implies that the difference between the pointers MUST BE A MULTIPLE OF THE ALIGNMENT FACTOR. Arbitrary copies will not have this property, hence, on such machines one must always have a byte-oriented copy routine to fall back on. For a 4-byte alignment machine, the test is something like: if ((p - q) & 3) *byte copy* else *struct copy* 2. If the difference between the pointers is a multiple of the machine alignment factor, then copying up until one is aligned will insure alignment of both. Hence, we simply need to insert a few moves to achieve alignment BEFORE the struct copy code I gave earlier. For a 4-byte alignment machine, the additional code is: if ((n >= 1) && (p & 1)) { *q = *p; ++q; ++p; --n; } if ((n >= 2) && (p & 2)) { *((struct t2 *) q) = *((struct t2 *) p); q+=2; p+=2; n-=2; } Notice that, with the above code as a prefix, trailing alignment is also satisfied (proof left as an exercise to the reader). 3. Although I know of no such C compiler, it is legal for a C compiler to make the size of a struct anything big enough to hold the things inside it. Hence, for example, a struct containing an array of 4 things might be the size of 5 things.... If this were done, the struct copy would nearly work; the only problem is that it could overshoot the end of the block. There is no general fix for this. hankd@ee.ecn.purdue.edu