Date: Tue, 14 Feb 2006 11:57:18 +0200 From: Giorgos Keramidas <keramida@ceid.upatras.gr> To: "M. Warner Losh" <imp@bsdimp.com> Cc: arch@freebsd.org, stefanf@freebsd.org, cperciva@freebsd.org, des@des.no Subject: Re: [releng_6 tinderbox] failure on sparc64/sparc64 Message-ID: <20060214095718.GC967@flame.pc> In-Reply-To: <20060213.210510.89039143.imp@bsdimp.com> References: <43F04494.4030900@freebsd.org> <20060213.094336.118368793.imp@bsdimp.com> <20060214083530.K22079@epsplex.bde.org> <20060213.210510.89039143.imp@bsdimp.com>
next in thread | previous in thread | raw e-mail | index | archive | help
On 2006-02-13 21:05, "M. Warner Losh" <imp@bsdimp.com> wrote: > In message: <20060214083530.K22079@epsplex.bde.org> > Bruce Evans <bde@zeta.org.au> writes: > : > It won't matter given how I'm going to fix this problem... > : > : Why not just access the object as an array of unsigned chars as someone > : wrote? Write it out 1 unsigned char at a time for the simple version. > : This avoids the complications. > > Because it has to be fed to the hardware 4 bytes at a time. That's still possible, using an intermediate unsigned char buffer, or if that's too much to ask (i.e. because keeping a duplicate copy of the 'foo' structure is a waste of memory), using a 4-byte scratch buffer and iterating over an (unsigned char *) pointer through `foo'. I think, that given a `foo' struct defined as: struct foo { uint32_t a; uint16_t b; uint16_t c; uint8_t d; uint8_t e; }; You are always allowed to use an (unsigned char *) pointer to iterate through its bytes, as in: #include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <string.h> struct foo { uint32_t a; uint16_t b; uint16_t c; uint8_t d; uint8_t e; }; int main(void) { struct foo foo; size_t k; memset(&foo, 0, sizeof(foo)); foo.a = 1; foo.b = 2; foo.c = 3; foo.d = 4; foo.e = 5; for (k = 0; k < sizeof(foo); k++) printf("%s%02x", k ? " " : "", *((unsigned char *)&foo + k)); putchar('\n'); return EXIT_SUCCESS; } This prints padding bytes correctly here, even with: $ CFLAGS='-std=c99 -pedantic' make WARNS=6 foo.c [...] $ ./foo 01 00 00 00 02 00 03 00 04 05 00 00 $ Then, if there's a 4-byte constraint, a single uint32_t can be used as a 'buffer': #include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <string.h> struct foo { uint32_t a; uint16_t b; uint16_t c; uint8_t d; uint8_t e; }; int main(void) { struct foo foo; size_t k, nbytes; uint32_t x; memset(&foo, 0, sizeof(foo)); foo.a = 1; foo.b = 2; foo.c = 3; foo.d = 4; foo.e = 5; for (k = 0; k < sizeof(foo); k++) printf("%s%02x", k ? " " : "", *((unsigned char *)&foo + k)); putchar('\n'); for (k = 0; k < sizeof(foo); k += 4) { nbytes = sizeof(uint32_t); if (sizeof(foo) - k < nbytes) { nbytes = sizeof(foo) - k; memset(&x, 0, sizeof(x)); } memcpy(&x, ((unsigned char *)&foo + k), nbytes); printf("%s%zdb/%08x", k ? " " : "", nbytes, x); } putchar('\n'); return EXIT_SUCCESS; } and it seems to work as expected here on a little-endian machine: $ ./foo 01 00 00 00 02 00 03 00 04 05 00 00 4b/00000001 4b/00030002 4b/00000504 This probably works much better than trying to cast the original into an array of uint32_t objects too :)
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20060214095718.GC967>