[releng_6 tinderbox] failure on sparc64/sparc64
Giorgos Keramidas
keramida at ceid.upatras.gr
Tue Feb 14 01:58:11 PST 2006
On 2006-02-13 21:05, "M. Warner Losh" <imp at bsdimp.com> wrote:
> In message: <20060214083530.K22079 at epsplex.bde.org>
> Bruce Evans <bde at 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 :)
More information about the freebsd-arch
mailing list