pointer alignment when int != char * 
Author Message
 pointer alignment when int != char *

If I were to want to implement malloc (or some such) on a machine where
sizeof(int) != sizeof(char *), how do I ensure that the pointer-values I
return are maximally aligned (eg, quad-aligned)? If sizeof(int)==sizeof(char *),
then I can cast the pointer to an int, do whatever arithmetic stuff is
required to it to get it to be aligned, then cast it back again - but of
course this won't work if information is lost by either of the casts.

Any hints?

(BTW, It's not really malloc I'm dealing with, I just lied about that one)

        %{
            Simon!
        %}

--
----------------------------------
| Simon Brown                    | UUCP:  seismo!mcvax!ukc!its63b!simon


| Scotland, UK.                  |
----------------------------------       "Life's like that, you know"



Tue, 17 Nov 1992 04:39:00 GMT  
 pointer alignment when int != char *

Quote:

>If I were to want to implement malloc (or some such) on a machine where
>sizeof(int) != sizeof(char *), how do I ensure that the pointer-values I
>return are maximally aligned (eg, quad-aligned)?

The same way as you would on any other machine: non-portably.
(What is your definition of quad-aligned?  4 * sizeof(char)?  There
are quit a few machines where this is not maximally aligned.)

For example, prime 64v mode:

char *alignpointer(p)
char *p;
{
    union {
        char *up;
        struct {
            unsigned fault:1;
            unsigned ring:2;    /* I may have the ring and extend bits exchanged */
            unsigned extend:1;  /* check before you try this on a real prime */
            unsigned segment:12;
            unsigned offset:16;
            unsigned bit:4;
            unsigned unused:12;
        } point;
    } un;
    int zerooffset;

    un.up = p;
    if(un.point.fault) return p; /* faulted pointer, not a valid address */
    zerooffset = un.point.offset == 0;
    un.point.offset = (un.point.offset | (un.point.extend & (un.point.bit!=0))
         + 1) & ~1; /* round offset up to next 4 byte boundry */
    un.point.extend = 0;/* and say it is at a 2-byte boundry */
    un.point.bit = 0;   /* unneded, but leave it clean */
    if(un.point.offset == 0 && !zerooffset) un.point.segment++;
    return un.up;

Quote:
}

Obviously, it would be easier to make sure to generate aligned pointers
in the first place.  Also I did not make all the assumptions that the C compiler
does, assuming you could have gotten the pointer via another language.

Uucp: {sdcrdcf,seismo!cit-vax}!oberon!castor!blarson
"How well do we use our freedom to choose the illusions we create?" -- Timbuk3


Thu, 17 Dec 1992 19:24:00 GMT  
 pointer alignment when int != char *

Quote:

>If I were to want to implement malloc (or some such) on a machine where
>sizeof(int) != sizeof(char *), how do I ensure that the pointer-values I
>return are maximally aligned (eg, quad-aligned)? If sizeof(int)==sizeof(char *),
>then I can cast the pointer to an int, do whatever arithmetic stuff is
>required to it to get it to be aligned, then cast it back again - but of
>course this won't work if information is lost by either of the casts.

First, do most of your arithmetic on (char *) data types, not on (int)s.

Second, forcing alignment may require converting your pointers to
integral types to do the rounding operations.  (long) is appropriate
for portable code.  (If a (char *) won't fit into a (long), you have
real problems!)

Third, it is difficult to portably determine alignment requirements.
Consider using something like the following:
        struct align
        {
                char    c0;
                union
                {
                        long    l1[2];
                        double  d1[2];
                        char    *cp1[2];
                        union
                        {
                                long    l2[2];
                                double  d2[2];
                                char    *cp2[2];
                        }       u1[2];
                }       u0;
        }       a;
        #define ALIGN   ((char *)&a.u0 - (char *)&a.c0)
(This example can probably be improved.)



Thu, 17 Dec 1992 16:33:00 GMT  
 pointer alignment when int != char *

Quote:
>integral types to do the rounding operations.  (long) is appropriate
>for portable code.  (If a (char *) won't fit into a (long), you have
>real problems!)

I'm not sure this is true anymore.  Don't some supercomputers make
longs 32 bits, long longs 64 bits, and have addresses > 32 bits and < 64 bits?
I seem to remember that someone said something like that recently.




Thu, 17 Dec 1992 20:13:00 GMT  
 pointer alignment when int != char *

Quote:


>>integral types to do the rounding operations.  (long) is appropriate
>>for portable code.  (If a (char *) won't fit into a (long), you have
>>real problems!)

>I'm not sure this is true anymore.  Don't some supercomputers make
>longs 32 bits, long longs 64 bits, and have addresses > 32 bits and < 64 bits?
>I seem to remember that someone said something like that recently.



Well, I am not positive about how the C compiler is organized,
(who wants to use a compiler which can barely vectorize on a cray?)
However,  the fortran compiler's primary data type for integers is
64 bits wide.  Internally, the addressing registers are only 24 bits
wide.  (The machine has no virtual memory, and 24 bits addresses
16 megawords which is still 128Mbytes, so the need for 32 bit or 64 bit
addressing is questionable.)  Anyways this has lead to much grief for
myself when I found library routines which never expected to see
things bigger than 8 Megwords (since the integers are signed.).

So I guess the m{*filter*}of the story is that
sizeof ( char *) < sizeof(int)  is also quite possible in some wierd
implementations.

                                -Castor Fu



Thu, 17 Dec 1992 21:07:00 GMT  
 pointer alignment when int != char *

->integral types to do the rounding operations.  (long) is appropriate
->for portable code.  (If a (char *) won't fit into a (long), you have
->real problems!)
-
-I'm not sure this is true anymore.  Don't some supercomputers make
-longs 32 bits, long longs 64 bits, and have addresses > 32 bits and < 64 bits?
-I seem to remember that someone said something like that recently.

What's a (long long)?  We were talking about portable code!



Thu, 17 Dec 1992 21:51:00 GMT  
 pointer alignment when int != char *
I sez:
  I'm not sure this is true anymore.  Don't some supercomputers make
  longs 32 bits, long longs 64 bits, and have addresses > 32 bits and < 64 bits?
  I seem to remember that someone said something like that recently.

Doug sez:
  What's a (long long)?  We were talking about portable code!

A long long is a kludge.  However, I seem to remember that it went something
like this:  a company was doing unix on a Amdahl (???) and the unix people
were really used to (xxx *) == 32 bits and (long) == 32 bits, and having
it otherwise broke all sorts of code.  So they gave people short, int, long,
and long long.  Yeah, it's gross.  But so was defining C in such an
ambiguous way.   It's really time for int8 int16 int32 int64 or some such
attempt at defining sizes with the type.




Thu, 17 Dec 1992 11:36:00 GMT  
 pointer alignment when int != char *

Quote:


>>(long) is appropriate for portable code.  (If a (char *) won't fit into a
>>(long), you have real problems!)

Hasn't ANSI removed all pretense of pointers being integerizable?

Quote:
>I'm not sure this is true anymore.  Don't some supercomputers make
>longs 32 bits, long longs 64 bits, and have addresses > 32 bits and < 64 bits?
>I seem to remember that someone said something like that recently.

Probably my article, which was hypothetical.  I was less concerned with the
cast of pointer to int, which is nonportable anyway, than with the kosherness
of having size_t and ptrdiff_t be larger than unsigned long.




Thu, 17 Dec 1992 19:31:00 GMT  
 pointer alignment when int != char *

Quote:

>Hasn't ANSI removed all pretense of pointers being integerizable?

No -- it doesn't REQUIRE that they be, but it does provide some constraints
in the case that the implementation supports this (as many do).


Thu, 17 Dec 1992 15:20:00 GMT  
 pointer alignment when int != char *
That is hideous.  I don't know what supercomputer you are referring
to but Crays have ints and longs both at 64 bits.  There are no super-longs.
When we did the compilers for the HEP Supercomputer (64 bit words),
we opted for 16 bit shorts, 64 bit ints,  and 64 bit longs.  There is
one more hardware supported type (half words-32 bits).  Avoiding things
that would really warp the language such as short long ints or long short
ints, and realizing that we really wanted int to be 64 bits (the convenient
size as stated in K&R and the standards), we settled for a seperate "hidden"
type that we try to avoid using except when necessary.  It was called
_int32, though the term "medium int" did come up in discussion.  By the
way, it was a real pain hacking pcc to do the extra int type.

-Ron



Thu, 17 Dec 1992 14:17:00 GMT  
 pointer alignment when int != char *
: That is hideous.  I don't know what supercomputer you are referring
: to but Crays have ints and longs both at 64 bits.  There are no super-longs.
: When we did the compilers for the HEP Supercomputer (64 bit words),
: we opted for 16 bit shorts, 64 bit ints,  and 64 bit longs.  There is
: one more hardware supported type (half words-32 bits).  Avoiding things...

Why not have int be 32 bits? That fits the requirement that
length char<=short<=int<=long. Not a comment, just a question...
--

  {chinet | philabs | sesimo}!steinmetz!crdos1!davidsen
"Stupidity, like virtue, is its own reward" -me



Thu, 17 Dec 1992 16:06:00 GMT  
 pointer alignment when int != char *

Quote:
>Why not have int be 32 bits? That fits the requirement that
>length char<=short<=int<=long. Not a comment, just a question...

There are two main considerations for the correct size to be used for (int)
when implementing C on a new system:

1.  (int) objects should be accessible quickly.  On a word-addressed
architecture, this argues for making them full words.

2.  (int)s must be usable for indexing arrays.  Depending on the address
space, one may have to either impose an artificial limit on array sizes
or else make (int)s longer than they might have been.  For example, on
a hypothetical PDP-11AX (which doesn't exist because it turned into a VAX),
one could have had 16 bits continue to be the natural integer data size but
24 or 32 bits could have been the preferred pointer size due to an extended
addressing scheme using base registers a la Gould.  The C implementor would
almost certainly have wanted to make the larger address space available on
such a machine, which would force some sort of accommodation to be made for
indexing char arrays -- probably by making (int)s as wide as char pointers.

I understand from hearsay that the IBM PC world (actually the Intel 8086
world) ran against this very problem, and instead of making a single sane
choice they ended up proliferating a variety of incompatible sets of
choices (hilariously called "models").  One hopes that a lesson was learned,
but I doubt it.



Thu, 17 Dec 1992 16:58:00 GMT  
 pointer alignment when int != char *

Quote:
> : When we did the compilers for the HEP Supercomputer (64 bit words),
> : we opted for 16 bit shorts, 64 bit ints,  and 64 bit longs.  There is
> : one more hardware supported type (half words-32 bits).  Avoiding things...
> Why not have int be 32 bits? That fits the requirement that
> length char<=short<=int<=long. Not a comment, just a question...

Because "int" is supposed to be a convenient size.  The convenient size for
us is 64 bits.  Since the largest number of variables are type "int" you
want to use something pretty efficient (like the word size).

By they way, you assumption that type "char" has some guaranteed relationship
to any of the integer types is wrong, although anyone who has "char"s that
aren't exactly eight bits is likely to cause many applications to die.

-Ron



Thu, 17 Dec 1992 15:25:00 GMT  
 pointer alignment when int != char *

Quote:

>>Why not have int be 32 bits? That fits the requirement that
>>length char<=short<=int<=long. Not a comment, just a question...

>There are two main considerations for the correct size to be used for (int)
>when implementing C on a new system:

>1.  (int) objects should be accessible quickly.  On a word-addressed
>architecture, this argues for making them full words.

[ I thought you mentioned that the 32 bit size was hardware supported.
On many machines the short math is faster than long (ie. vax, 68000). ]

Quote:

>2.  (int)s must be usable for indexing arrays.  Depending on the address
>space, one may have to either impose an artificial limit on array sizes
>or else make (int)s longer than they might have been.  For example, on

[ The 32 bit size allows an acceptable range as a subscript, although at
some point 4GB won't be enough, most of the problems using big memory
are also using multiple arrays less than 2GB. ]

Quote:
>I understand from hearsay that the IBM PC world (actually the Intel 8086
>world) ran against this very problem, and instead of making a single sane
>choice they ended up proliferating a variety of incompatible sets of
>choices (hilariously called "models").  One hopes that a lesson was learned,
>but I doubt it.

That's the point I was making in my posting... the problems occur when
the int won't hold an address, and then mainly because some <deleted> is
playing fast & loose with bit fidling in pointers or some such. The
major problems with "models" would go away if someone made the large
model int the same length as the large model pointer.

I've been fighting with this in pathalias, trying to get it to run on an
80*86 machine, and finding that (a) it does all its own memory
allocation, and (b) it uses ints to hold addresses while doing it. This
kind of non-portable code will fail on machines which are not byte
addressed, and which use a pointer which looks like a word address and
character offset.

X3J11 covered this very well, pointers are not forced to be the size of
int, they are not even the size of each other! Code written for large
model 80*86 will almost always run on any other machine, assuming that
it doesn't use calls to the hardware, etc.
--

  {chinet | philabs | sesimo}!steinmetz!crdos1!davidsen
"Stupidity, like virtue, is its own reward" -me



Thu, 17 Dec 1992 13:00:00 GMT  
 
 [ 27 post ]  Go to page: [1] [2]

 Relevant Pages 

1. char pointers vs. int pointers

2. int to char / char to int

3. char to int, int to char...

4. conversion int to char, char to int ?????

5. char *fnpars(const char *fn, int p, int v)

6. Determing alignment of (char *) pointer

7. Help with pointers, and char -> int

8. Casting between int and pointer to char

9. convert char to short int via pointer?...

10. Comparison with pointer to pointer to char, and char

11. A char pointer (char *) vs. char array question

12. int gethostname(char FAR* name, int len)

 

 
Powered by phpBB® Forum Software