Alignment on stack arrays

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • H.K. Kingston-Smith

    Alignment on stack arrays

    I understand that a line like

    char *a = malloc(64) ;

    when succeeding will initialize a to a pointer that is aligned at worst
    on the natural boundary of the underlying architecture, possibly on a
    multiple thereof.

    Now what about

    char a[64] ;

    Do we have the guarantee that &a[0] is always going to be aligned
    according to the same criteria as above?
  • Richard Tobin

    #2
    Re: Alignment on stack arrays

    In article <g33gn4$fj6$1@r egistered.motza rella.org>,
    H.K. Kingston-Smith <HKK-S@yahoo.comwrot e:
    > Now what about
    >
    > char a[64] ;
    >
    >Do we have the guarantee that &a[0] is always going to be aligned
    >according to the same criteria as above?
    No. You could use a union to ensure it is aligned suitably for
    some particular other type(s).

    -- Richard


    --
    In the selection of the two characters immediately succeeding the numeral 9,
    consideration shall be given to their replacement by the graphics 10 and 11 to
    facilitate the adoption of the code in the sterling monetary area. (X3.4-1963)

    Comment

    • Richard Heathfield

      #3
      Re: Alignment on stack arrays

      H.K. Kingston-Smith said:
      I understand that a line like
      >
      char *a = malloc(64) ;
      >
      when succeeding will initialize a to a pointer that is aligned at worst
      on the natural boundary of the underlying architecture, possibly on a
      multiple thereof.
      Putting it another way, it will be correctly aligned for any type. That's
      because malloc doesn't know what type you're going to use the memory for.
      Now what about
      >
      char a[64] ;
      >
      Do we have the guarantee that &a[0] is always going to be aligned
      according to the same criteria as above?
      It will be correctly aligned for char on that system. It is not guaranteed (or
      even particularly likely) that it will be correctly aligned for any other
      (non-char) type.

      --
      Richard Heathfield <http://www.cpax.org.uk >
      Email: -http://www. +rjh@
      Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
      "Usenet is a strange place" - dmr 29 July 1999

      Comment

      • Barry Schwarz

        #4
        Re: Alignment on stack arrays

        On Sun, 15 Jun 2008 16:41:09 +0000 (UTC), "H.K. Kingston-Smith"
        <HKK-S@yahoo.comwrot e:
        > I understand that a line like
        >
        > char *a = malloc(64) ;
        >
        >when succeeding will initialize a to a pointer that is aligned at worst
        >on the natural boundary of the underlying architecture, possibly on a
        >multiple thereof.
        malloc will return an address that is properly aligned for any type of
        C object (at least in part because malloc has no idea what the type of
        a is). There may well be other objects available in the architecture
        with other alignment requirements that malloc knows nothing about.
        >
        > Now what about
        >
        > char a[64] ;
        >
        >Do we have the guarantee that &a[0] is always going to be aligned
        >according to the same criteria as above?
        No. In this case, the compiler knows at a[0] is a char and it only
        has to align a on a "char boundary".

        On most systems char has no alignment requirements, or equivalently is
        aligned on a multiple of one, so this is not the best example.
        Consider a non-C99 system where long and double are the most stringent
        and need to be aligned on an 8-byte boundary while int needs only be
        on a 4-byte boundary. malloc must return an address which is a
        multiple of 8. But an int (or an array of int) can be aligned on any
        multiple of 4 (of which only half are also multiples of 8).


        Remove del for email

        Comment

        • Keith Thompson

          #5
          Re: Alignment on stack arrays

          "H.K. Kingston-Smith" <HKK-S@yahoo.comwrit es:
          I understand that a line like
          >
          char *a = malloc(64) ;
          >
          when succeeding will initialize a to a pointer that is aligned at worst
          on the natural boundary of the underlying architecture, possibly on a
          multiple thereof.
          >
          Now what about
          >
          char a[64] ;
          >
          Do we have the guarantee that &a[0] is always going to be aligned
          according to the same criteria as above?
          As others have said, the answer is no.

          However, it's fairly likely that a 64-byte object will be more
          strictly aligned anyway, simply because it can make some operations
          more efficient. For example, if you call

          memset(a, 0, sizeof a);

          then memset() *might* be able to zero a word at a time if a is
          word-aligned.

          Don't let the fact that a is *likely* to be word-aligned (whatever a
          "word" happens to be) fool you into thinking that it's guaranteed.

          Others have also suggested using a union to force it to have a
          stricter alignment. That's likely to be good enough, but if you want
          the same alignment guarantees provided by malloc(), there's really no
          portable way to do it.

          --
          Keith Thompson (The_Other_Keit h) kst-u@mib.org <http://www.ghoti.net/~kst>
          Nokia
          "We must do something. This is something. Therefore, we must do this."
          -- Antony Jay and Jonathan Lynn, "Yes Minister"

          Comment

          • Bart

            #6
            Re: Alignment on stack arrays

            On Jun 15, 5:41 pm, "H.K. Kingston-Smith" <HK...@yahoo.co mwrote:
                    I understand that a line like
            >
                    char *a = malloc(64) ;
            >
            when succeeding will initialize a to a pointer that is aligned at worst
            on the natural boundary of the underlying architecture, possibly on a
            multiple thereof.
            >
                    Now what about
            >
                    char a[64] ;
            >
            Do we have the guarantee that &a[0] is always going to be aligned
            according to the same criteria as above?
            I don't know if you actually need a solution or not, but anyway..

            If you're happy using pointers to the 'stack' arrays, then perhaps
            something like the following. I need a 16-character array to be
            aligned to a multiple of 8. An extra 7 bytes are allocated and a
            pointer to the array is stepped until the alignment is correct.

            This makes some assumptions however about being able to access the
            bottom 3 address lines via the pointer value.

            #include <stdio.h>

            int main(void)
            {
            char a0[23]; /* Need char a[16] */
            char *a=a0;

            while ((int)a & 7) ++a;

            printf("%x\n",a );

            }

            --
            Bartc

            Comment

            • vippstar@gmail.com

              #7
              Re: Alignment on stack arrays

              On Jun 15, 11:28 pm, Bart <b...@freeuk.co mwrote:
              On Jun 15, 5:41 pm, "H.K. Kingston-Smith" <HK...@yahoo.co mwrote:
              >
              I understand that a line like
              >
              char *a = malloc(64) ;
              >
              when succeeding will initialize a to a pointer that is aligned at worst
              on the natural boundary of the underlying architecture, possibly on a
              multiple thereof.
              >
              Now what about
              >
              char a[64] ;
              >
              Do we have the guarantee that &a[0] is always going to be aligned
              according to the same criteria as above?
              >
              I don't know if you actually need a solution or not, but anyway..
              >
              If you're happy using pointers to the 'stack' arrays, then perhaps
              something like the following. I need a 16-character array to be
              aligned to a multiple of 8. An extra 7 bytes are allocated and a
              pointer to the array is stepped until the alignment is correct.
              >
              This makes some assumptions however about being able to access the
              bottom 3 address lines via the pointer value.
              That code snipped makes much more assumptions than just that.
              >
              #include <stdio.h>
              >
              int main(void)
              {
              char a0[23]; /* Need char a[16] */
              char *a=a0;
              >
              while ((int)a & 7) ++a;
              >
              printf("%x\n",a );
              >
              }
              That code is rubbish. Please don't recommend code that doesn't work.

              Comment

              • Bart

                #8
                Re: Alignment on stack arrays

                On Jun 15, 9:43 pm, vipps...@gmail. com wrote:
                On Jun 15, 11:28 pm, Bart <b...@freeuk.co mwrote:
                #include <stdio.h>
                >
                int main(void)
                {
                char a0[23];     /* Need char a[16] */
                char *a=a0;
                >
                while ((int)a & 7) ++a;
                >
                printf("%x\n",a );
                >
                }
                >
                That code is rubbish. Please don't recommend code that doesn't work
                It's not a recommendation. It's just ideas. But as for not working:

                #include <stdio.h>

                int main(void)
                {
                char a0[23];
                char *a=a0;

                printf("Address before: %x\n",a);

                while ((int)a & 7) ++a;

                printf("Address after: %x\n",a);
                }

                Output:

                Address before: 12ff59
                Address after: 12ff60


                --
                Bartc

                Comment

                • Keith Thompson

                  #9
                  Re: Alignment on stack arrays

                  Bart <bc@freeuk.comw rites:
                  [...]
                  If you're happy using pointers to the 'stack' arrays, then perhaps
                  something like the following. I need a 16-character array to be
                  aligned to a multiple of 8. An extra 7 bytes are allocated and a
                  pointer to the array is stepped until the alignment is correct.
                  >
                  This makes some assumptions however about being able to access the
                  bottom 3 address lines via the pointer value.
                  >
                  #include <stdio.h>
                  >
                  int main(void)
                  {
                  char a0[23]; /* Need char a[16] */
                  char *a=a0;
                  >
                  while ((int)a & 7) ++a;
                  >
                  printf("%x\n",a );
                  >
                  }
                  That might be acceptable in system-specific code (though incrementing
                  the address one at a time is wasteful).

                  If you want alignment matching a particular type, declare an object of
                  that type or use a union. If you want alignment appropriate for any
                  possible type, use malloc.

                  --
                  Keith Thompson (The_Other_Keit h) kst-u@mib.org <http://www.ghoti.net/~kst>
                  Nokia
                  "We must do something. This is something. Therefore, we must do this."
                  -- Antony Jay and Jonathan Lynn, "Yes Minister"

                  Comment

                  • Bart

                    #10
                    Re: Alignment on stack arrays

                    "Keith Thompson" <kst-u@mib.orgwrote in message
                    news:lniqwacqay .fsf@nuthaus.mi b.org...
                    Bart <bc@freeuk.comw rites:
                    >char a0[23]; /* Need char a[16] */
                    >char *a=a0;
                    >>
                    >while ((int)a & 7) ++a;
                    That might be acceptable in system-specific code (though incrementing
                    the address one at a time is wasteful).
                    That's true. Maybe it could even be done in the char *a=a0 line. But I
                    was more likely to get it right this way..
                    >
                    If you want alignment matching a particular type, declare an object of
                    that type or use a union.
                    Yes, but doesn't the union get in the way? You'd have to use u.a[i]
                    instead of a[i]. If there already existed lots of references to a, it
                    would mean many changes and is a little obfuscatory.

                    Also the obvious solution (to use, for example, int a[16] then access
                    it as as though it were char a[64]), would have casts sprinkled
                    everywhere. The use of macros could alleviate these shortcomings
                    although the global nature of macros might be a problem.

                    My pointer idea leaves the original code using a[] unchanged but at a
                    cost of a pointer dereference (plus a few wasted bytes in the array).
                    This might be acceptable if a word-aligned char buffer in automatic
                    storage is what's wanted.

                    --
                    Bartc

                    Comment

                    • vippstar@gmail.com

                      #11
                      Re: Alignment on stack arrays

                      On Jun 16, 12:00 am, Bart <b...@freeuk.co mwrote:
                      On Jun 15, 9:43 pm, vipps...@gmail. com wrote:
                      >
                      On Jun 15, 11:28 pm, Bart <b...@freeuk.co mwrote:
                      #include <stdio.h>
                      >
                      int main(void)
                      {
                      char a0[23]; /* Need char a[16] */
                      char *a=a0;
                      >
                      while ((int)a & 7) ++a;
                      >
                      printf("%x\n",a );
                      >
                      }
                      >
                      That code is rubbish. Please don't recommend code that doesn't work
                      >
                      It's not a recommendation. It's just ideas. But as for not working:
                      >
                      #include <stdio.h>
                      >
                      int main(void)
                      {
                      char a0[23];
                      char *a=a0;
                      >
                      printf("Address before: %x\n",a);
                      >
                      while ((int)a & 7) ++a;
                      >
                      printf("Address after: %x\n",a);
                      >
                      }
                      >
                      Output:
                      >
                      Address before: 12ff59
                      Address after: 12ff60
                      What is that supposed to prove?
                      You invoke undefined behavior in the while loop and in the printf call
                      and there is no 'return' from main.
                      Here's a possible fix:
                      /* a = ... */
                      while((uintptr_ t)a & 7) ++a;
                      printf("%p\n", (void *)a);

                      But its purpose I am not aware of.

                      Comment

                      • Flash Gordon

                        #12
                        Re: Alignment on stack arrays

                        Bart wrote, On 15/06/08 22:00:
                        On Jun 15, 9:43 pm, vipps...@gmail. com wrote:
                        >On Jun 15, 11:28 pm, Bart <b...@freeuk.co mwrote:
                        >
                        >>#include <stdio.h>
                        >>int main(void)
                        >>{
                        >>char a0[23]; /* Need char a[16] */
                        >>char *a=a0;
                        >>while ((int)a & 7) ++a;
                        >>printf("%x\n" ,a);
                        >>}
                        >That code is rubbish. Please don't recommend code that doesn't work
                        >
                        It's not a recommendation. It's just ideas. But as for not working:
                        <snip>

                        Implementations where pointers are larger than int are becoming popular
                        again (a lot of 64 bit implementations have this property) and on such
                        implementations casting the pointer to int invokes undefined behaviour.
                        It may well still work (and is likely to on a lot of implementations )
                        but it is not guaranteed and the compiler is under no obligation to make
                        it work on such systems.
                        --
                        Flash Gordon

                        Comment

                        • Flash Gordon

                          #13
                          Re: Alignment on stack arrays

                          Bart wrote, On 15/06/08 23:39:
                          "Keith Thompson" <kst-u@mib.orgwrote in message
                          news:lniqwacqay .fsf@nuthaus.mi b.org...
                          >Bart <bc@freeuk.comw rites:
                          >
                          >>char a0[23]; /* Need char a[16] */
                          >>char *a=a0;
                          >>>
                          >>while ((int)a & 7) ++a;
                          >
                          >That might be acceptable in system-specific code (though incrementing
                          >the address one at a time is wasteful).
                          >
                          That's true. Maybe it could even be done in the char *a=a0 line. But I
                          was more likely to get it right this way..
                          Well, it is often said here that one should get it right before worrying
                          about efficiency, but...
                          >If you want alignment matching a particular type, declare an object of
                          >that type or use a union.
                          >
                          Yes, but doesn't the union get in the way? You'd have to use u.a[i]
                          instead of a[i]. If there already existed lots of references to a, it
                          would mean many changes and is a little obfuscatory.
                          Why?

                          char *a = a0.c

                          Where a0.c is the part of the union that is a char array.
                          Also the obvious solution (to use, for example, int a[16] then access
                          it as as though it were char a[64]), would have casts sprinkled
                          everywhere.
                          Why?

                          int a0[WHATEVER];
                          char *a = (char*)a0;
                          The use of macros could alleviate these shortcomings
                          although the global nature of macros might be a problem.
                          >
                          My pointer idea leaves the original code using a[] unchanged but at a
                          cost of a pointer dereference (plus a few wasted bytes in the array).
                          This might be acceptable if a word-aligned char buffer in automatic
                          storage is what's wanted.
                          There is nothing about the other methods that requires changing the rest
                          of the code. You used an additional pointer, and that additional pointer
                          could be used with any other conceivable method!
                          --
                          Flash Gordon

                          Comment

                          • Bart

                            #14
                            Re: Alignment on stack arrays

                            On Jun 16, 12:15 am, vipps...@gmail. com wrote:
                            On Jun 16, 12:00 am, Bart <b...@freeuk.co mwrote:
                            #include <stdio.h>
                            >
                            int main(void)
                            {
                            char a0[23];
                            char *a=a0;
                            >
                            printf("Address before: %x\n",a);
                            >
                            while ((int)a & 7) ++a;
                            >
                            printf("Address after:  %x\n",a);
                            >
                            }
                            >
                            Output:
                            >
                            Address before: 12ff59
                            Address after:  12ff60
                            >
                            What is that supposed to prove?
                            That the int representation of a pointer has had it's 3 low bits
                            changed from 001 to 000. Which is very likely to correspond to the low
                            bits of the physical address.
                            You invoke undefined behavior in the while loop and in the printf call
                            Why? Converting a pointer to an int isn't exactly unheard of. It's
                            best to use an int big enough to represent the pointer, but I have a
                            feeling it will just be truncated if not, and I'm only interested in
                            the bottom 3 bits anyway. The pointer is only changed using ++a.

                            For printing, again I'm interested in the /int/ representation of the
                            pointer (also I'd forgotten about %p).
                            and there is no 'return' from main.
                            Well my compilers (3 out of 4 anyway) keep insisting on not
                            complaining about it.. so I'm not going to argue when a 5-line
                            expression of an /idea/ is at stake.
                            Here's a possible fix:
                            /* a = ... */
                            while((uintptr_ t)a & 7) ++a;
                            printf("%p\n", (void *)a);
                            Yes nice textbook stuff.
                            >
                            But its purpose I am not aware of
                            Clearly not.

                            --
                            Bartc

                            Comment

                            • vippstar@gmail.com

                              #15
                              Re: Alignment on stack arrays

                              On Jun 16, 3:05 am, Bart <b...@freeuk.co mwrote:
                              On Jun 16, 12:15 am, vipps...@gmail. com wrote:
                              >
                              >
                              >
                              On Jun 16, 12:00 am, Bart <b...@freeuk.co mwrote:
                              #include <stdio.h>
                              >
                              int main(void)
                              {
                              char a0[23];
                              char *a=a0;
                              >
                              printf("Address before: %x\n",a);
                              >
                              while ((int)a & 7) ++a;
                              >
                              printf("Address after: %x\n",a);
                              >
                              }
                              >
                              Output:
                              >
                              Address before: 12ff59
                              Address after: 12ff60
                              >
                              What is that supposed to prove?
                              >
                              That the int representation of a pointer has had it's 3 low bits
                              changed from 001 to 000. Which is very likely to correspond to the low
                              bits of the physical address.
                              It is not guaranteed that int can correctly represent a pointer.
                              You invoke undefined behavior in the while loop and in the printf call
                              >
                              Why? Converting a pointer to an int isn't exactly unheard of. It's
                              It is not unheard, so?
                              best to use an int big enough to represent the pointer, but I have a
                              int is not guaranteed to be big enough to represent the pointer.
                              Perhaps you mean integer type big enough; in which case yes, there is
                              intptr_t and uintptr_t, and indeed it's best to use these.
                              feeling it will just be truncated if not, and I'm only interested in
                              the bottom 3 bits anyway. The pointer is only changed using ++a.
                              It has nothing to do with "truncated" .
                              See 6.3.2.3 p 6
                              For printing, again I'm interested in the /int/ representation of the
                              pointer (also I'd forgotten about %p).
                              What int representation? That doesn't make sense. You are passing
                              different types than the ones expected in a variadic function/macro
                              which causes undefined behavior.
                              and there is no 'return' from main.
                              >
                              Well my compilers (3 out of 4 anyway) keep insisting on not
                              complaining about it.. so I'm not going to argue when a 5-line
                              expression of an /idea/ is at stake.
                              Most likely because you compile with C99 mode, in which is fine not to
                              return a value from main.
                              Here's a possible fix:
                              /* a = ... */
                              while((uintptr_ t)a & 7) ++a;
                              printf("%p\n", (void *)a);
                              >
                              Yes nice textbook stuff.
                              But, some lines ago you said it's *best* to use an integer type big
                              enough.

                              Comment

                              Working...