Memory Alignment

Posted on 2006-05-10
Last Modified: 2012-06-27
Please can someone explain the memory alignment for advancing an short array pointer cast to a void*.
Question by:luoys
    LVL 32

    Expert Comment

    Memory alignment, in the x86 world at least, has to do with performance rather than operability.  That means that the x86 family CPUs can access a byte of data regardless of how it's aligned in memory but that doing so might be much slower than if the data were aligned on a 32-bit or with newer CPUs, 64-bit boundary.  Some CPUs, most notably the HP PA RISC, PowerPC, and Sun SPARC chips cannot access data on anything but a 32-bit boundary and attempts to do an unaligned access will cause a fault.

    So what is alignment?  We often think of byte in programming and bytes are 8-bit pieces of data.  On an 8-bit CPU (like an 8080, Z80, 6800, 6502, etc.) alignment is not an issue since each memory address represents one and only one byte.

    On a 16-bit CPU (8086, 68000, etc.) it's more complicated.  Each memory address now represents 16-bits or TWO bytes.  So when you access a memory element you may be interested in the full 16-bit value or you may be interested in either the upper or lower 8-bits of the 16-bit value.  Here's where it gets tricky.  Normally you'd store that 16-bit value at an EVEN address like 0, 2, 4, 6, ... since the ODD addresses, 1, 3, 5, 7, ... represent the UPPER 8-bits of the 16-bit value, at least on an x86 CPU.  That's OK and you can read BYTES at any address.  But what do you get if you try to READ a 16-bit WORD at address 1?  This is alignment at work.  In the x86 CPU, this causes TWO read cycles, one to get the upper byte of address 0 and another to get the lower byte of address 2 so that when they are assembled you can have the 16-bit value at address 1.  So while this is possible, on the x86 CPU at least, it's not desirable for the most part because it takes 2X as long to read.  

    On a 32-bit CPU (80386 and beyond) you have even more possibilities since any address has possibly 4 8-bit values, two 16-bit values, or one 32-bit values.  And even more alignment confusion is possible.

    In general, when programming, it's best to let the compiler adjust the alignment automatically for best performance on your target CPU.  It will often add padding bytes when needed so that it keeps data aligned on a 32-bit boundary.

    Why would you NOT want this to happen?  There are some specific reasons.  The most common is when you have an existing data structure (perhaps from a database a network socket or something else you have to live with and can't change) and you must either read or write to that structure in a compatible way.  While there are other ways to do this that don't involve non-aligned access, you MAY want to use this option to make your job simpler.
    LVL 3

    Accepted Solution

    Adding to what jhance said, I think good alignment also comes into play when optimising code, and use of the processor's onchip L1 and L2 caches, for similar reasons.  Also, some processors are actually unable to do non-aligned reads.  If you try to do one, the processor will fault, stop running your program, and jump to an error routine.  

    Because byte alignment is something very specific to processor type, its something you shouldn't worry about while programming, unless you really _really_ have to.  In addition to that, different compilers and architectures have different sizes for things like "short" "int", and pointers, making it harder to write cross-platform compatible code.  void* pointers should be avoided if possible, as they throw away valuable information on the type/size of the data its pointing at or representing.

    Back to your question: once a pointer is cast to "void *", there is no way of knowing what size datatype it was pointing to in the first place, so it can't move appropriately.  My compiler (gcc on FreeBSD on an Intel celeron) generates increments of 1 to a void* pointer, even if it was cast from a 4-byte type:

      int t[2]; // an array of integers
      int *t2 = t; // an integer pointer
      void *t3 = (void *)t; // an integer pointer cast to a void*

      printf("%x %x %x\n",t,t2,t3); // print out the address that the pointer points to
      printf("%x %x %x\n",t+1,t2+1,t3+1); // print out the address "plus one"


      bfbfe830 bfbfe830 bfbfe830
      bfbfe834 bfbfe834 bfbfe831

    You can see that the two integer pointers incremented by 4 (which is sizeof(int)), while the void* pointer has only incremented by one.

    Write Comment

    Please enter a first name

    Please enter a last name

    We will never share this with anyone.

    Featured Post

    Highfive Gives IT Their Time Back

    Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

    This is about my first experience with programming Arduino.
    If you’re thinking to yourself “That description sounds a lot like two people doing the work that one could accomplish,” you’re not alone.
    Viewers will learn how to properly install Eclipse with the necessary JDK, and will take a look at an introductory Java program. Download Eclipse installation zip file: Extract files from zip file: Download and install JDK 8: Open Eclipse and …
    In this seventh video of the Xpdf series, we discuss and demonstrate the PDFfonts utility, which lists all the fonts used in a PDF file. It does this via a command line interface, making it suitable for use in programs, scripts, batch files — any pl…

    758 members asked questions and received personalized solutions in the past 7 days.

    Join the community of 500,000 technology professionals and ask your questions.

    Join & Ask a Question

    Need Help in Real-Time?

    Connect with top rated Experts

    9 Experts available now in Live!

    Get 1:1 Help Now