From: diamond@jit533.jit.dec.com (Norman Diamond)
Subject: Re: Is this allowed in C?
Reply-To: diamond@jit.dec.com (Norman Diamond)
Organization: Digital Equipment Corporation Japan , Tokyo
Date: Fri, 22 Jan 1993 01:25:02 GMT

In article <C17p4n.Dx8@undergrad.math.waterloo.edu> bbobak@undergrad.math.waterloo.edu (Brad Bobak) writes:

Well, I noticed a few years ago that most of the practical-oriented stuff
moved to the new Computer Engineering department, but surely there should
still be some consultants or TAs that could help with this kind of problem?

> I was wondering if the following was valid in C.
> struct astruct { int something; int something_else; } blah;
> main() {
>    char *store;
>    store = malloc(sizeof(blah));
>    memcpy(store, &blah, sizeof(blah));
>    /* how about this? */
>    {
>        int another_int = 5;
>        memcpy(&((struct astruct *)store)->something, &another_int,
>               sizeof(int));
>    }

The C standard guarantees that whenever malloc() succeeds (which you forgot
to check), the value will point to storage suitably aligned for everything,
including structs.  So (struct astruct *)store can indeed be used as a pointer
to a struct astruct.

Pedantically, the standard forgot to say that when pointers to objects are
converted to pointers to void, it should be possible to use the pointers to
void in calls to memcpy() and other such functions.  However, I don't think
any implementor would dare to play games with this.

> and something else similar:
>#define CHAR_MASK ((1 << BITS_IN_CHAR) - 1)
>/* I realize this might fail if sizeof(int) == sizeof(char), if [...] */

This is indeed possible.  Why not use UCHAR_MAX?

> main() {
>    int val;
>    char *store;
>    int ct;
>    store = malloc(sizeof(val));
>    for (ct=0; ct<sizeof(int); ct++)
>        store[ct] = (val >> (ct * BITS_IN_CHAR)) & CHAR_MASK;
>    for (val=0, ct=0; ct<sizeof(int); ct++)
>        val |= store[ct] << (ct * BITS_IN_CHAR);

Looks reasonable to me.

> The reason I'm doing it this way is that I've made a memory allocation
>  library. And some systems require special alignment of data. So to
>  archive something, I have to copy it to a char array.

You mean that you might write the archive to a file and read it back on
another system?  What happens if you write the file on a system with
8-bit chars and read it back on a system with 9-bit chars?

>This next question probably has surfaced a few times, but is there any way
>to guarantee the right alignment of arbritary data on various architectures?

Whenever you declare a variable (an int or a struct of some sort or whatever)
the implementation has to be able to handle it.  If the implementation fails
to align it properly, then the implementation has to work it out somehow,
generating extra slow code if necessary.  And when malloc() succeeds, it
returns a pointer that you're allowed to use for any type of object.  However,
if you want some implementation to provide alignments that will work for some
different implementation, you're usually out of luck.
--
Norman Diamond                diamond@jit.dec.com
If this were the company's opinion, I wouldn't be allowed to post it.
Pardon me?  Or do I have to commit a crime first?
Newsgroups: comp.std.c