Does UNALIGNED attribute exist in GNU C?

Discussion in 'C Programming' started by Pavel A., May 19, 2005.

  1. Pavel A.

    Pavel A. Guest


    What is equivalent of __unaligned attribute in GNU C?
    I've searched for some time and it seems that it just does not exist...

    For HP and new Microsoft compilers it works this way:
    long_pointer = (some unaligned address)
    long_value = (* (__unaligned long *) long_pointer );

    This causes the compiler to emit code that gets the value
    in some slow but sure way, but avoiding exceptions

    No need to suggest workarounds please...

    Pavel A., May 19, 2005
    1. Advertisements

  2. Pavel A.

    Roger Leigh Guest

    Hash: SHA1

    It appears not to. That's probably because it should not be needed
    unless your code is buggy. If your code is standard C, the compiler
    should have aligned everything nicely for you. However, you didn't
    post the code that creates the unaligned pointer.

    - - Some CPUs allow unaligned access.
    - - Some operating systems can transparently handle unaligned access on
    systems that don't support it.

    - --
    Roger Leigh
    Printing on GNU/Linux?
    Debian GNU/Linux
    GPG Public Key: 0x25BFB848. Please sign and encrypt your mail.
    Version: GnuPG v1.4.1 (GNU/Linux)
    Comment: Processed by Mailcrypt 3.5.8 <>

    -----END PGP SIGNATURE-----
    Roger Leigh, May 19, 2005
    1. Advertisements

  3. [fu-t set]

    in comp.lang.c i read:
    correct -- there is nothing standard.
    those who know me have no need of my name, May 20, 2005
  4. Pavel A.

    Pavel A. Guest

    Thanks Roger for your reply.
    I was looking how to implement functions like LoadUnalignedLong /
    (the need for these is obvious... if you get unaligned structure from file
    or network etc).
    So will do it anyway else.

    Pavel A., May 22, 2005
  5. Pavel A.

    CBFalconer Guest

    Please don't toppost. It is not acceptable in c.l.c. See sig

    There is no such need. How do you get an "unaligned structure"?
    All you can receive from a network of file is some gestalt of
    bytes, which should have a defined relationship to a field in a
    structure. The details of a structure are not valid outside the
    system that created it, and can be freely changed, even by a
    compiler upgrade.

    Some informative links:
    CBFalconer, May 22, 2005
  6. Pavel A.

    Roger Leigh Guest

    Hash: SHA1

    [Please don't top-post]
    I've never seen those non-standard functions. Due to the hideous
    naming, I assume they come from MS Windows?

    The need for them aside, you could always memcpy to a known aligned
    memory location before reading/writing. It should be fairly cheap,
    but still less than ideal. If your software is properly written, you
    simply won't have alignment issues.

    - --
    Roger Leigh
    Printing on GNU/Linux?
    Debian GNU/Linux
    GPG Public Key: 0x25BFB848. Please sign and encrypt your mail.
    Version: GnuPG v1.4.1 (GNU/Linux)
    Comment: Processed by Mailcrypt 3.5.8 <>

    -----END PGP SIGNATURE-----
    Roger Leigh, May 22, 2005
  7. Pavel A.

    Richard Bos Guest

    You'd say so, but AFAICT not even that.
    If you have a halfway decently defined network or file format, you won't
    be reading directly into your objects if that's impossible. You'll be
    manipulating the byte _values_, rather than their representations in

    Richard Bos, May 23, 2005
  8. I respectfully disagree: In networking applications, for performance
    reasons (to avoid data copying) one must frequently deal with portions of
    buffers that are not correctly aligned.
    Thomas Carter, Jun 18, 2005
  9. Pavel A.

    Tim Prince Guest

    That depends on what you mean by unaligned. The C standards don't allow
    the kinds of type punning which would place, for example, a long long
    int at an odd short int address. Code which does so is non-portable.
    Even Microsoft C, in the newer 64-bit versions, gets away from the
    requirement to maximize support of 64-bit data located on any 32-bit
    boundary, but this NG is about standard C.
    If you mean, for example, a string of ints starting at any legal int
    boundary, that's the default, and doesn't require any attribute or
    pragma. gcc does support specification of higher alignments, such as
    those which would allow the use of aligned pair load and store instructions.
    Tim Prince, Jun 18, 2005
  10. This is a generalisation which is the for most part wrong. Not totally
    wrong but still mostly wrong. However a discussion of why is beyond the
    scope of comp.lang.c (i.e. where I am reading this).

    Lawrence Kirby, Jun 19, 2005
  11. typedef unsigned int UInt32 ;
    UInt32 * x = (UInt32 *) malloc(10) ;
    UInt32 * p = x + 1 ;

    f(p) ;

    f() is now dealing with an unaligned buffer. Lots of examples similar to
    this can be found e.g. in the OpenSSL library.

    That's what I meant.
    Thomas Carter, Jun 19, 2005
  12. No, it isn't. Perhaps you need a refresher on how 'C' pointers work?

    Paul Pluzhnikov, Jun 19, 2005
  13. 1) Wrong. p will point to x + sizeof(UInt32) .
    2) If UInt32 means "unsigned int 32 bits long" there is no guarantee
    that a plain "unsigned int" is 32 bits long. Actually, with my
    compiler & platform of choice, it is 64 bits long.
    Maurizio Loreti, Jun 19, 2005
  14. No it isn't.

    Go over the following carefully, testing it with your implementation.
    Then go back to your elementary C text and learn how pointer arithmetic

    #include <stdio.h>
    #include <stdlib.h>

    #define MAGICNUMBER 10

    int main(void)
    unsigned int *x = malloc(MAGICNUMBER);
    unsigned int *p = x + 1;
    unsigned i;
    if (!x) {
    fprintf(stderr, "The allocation of x failed.\n"
    "Bailing out ...\n");
    printf("The buffer x is of %u unsigned ints.\n"
    "Each is properly aligned.\n"
    "The addresses x are:\n", MAGICNUMBER);
    for (i = 0; i < MAGICNUMBER; i++)
    printf(" &x[%u] = %p, x+%u = %p\n",
    i, (void *) &x, i, (void *) (x + i));
    printf("\nAnd p, initialized to point at x + 1, has the\n"
    "same value as the correctly aligned &x[1] above:\n"
    " p = %p\n", (void *) p);
    return 0;

    [output on my implementation]
    The buffer x is of 10 unsigned ints.
    Each is properly aligned.
    The addresses x are:
    &x[0] = 20d50, x+0 = 20d50
    &x[1] = 20d54, x+1 = 20d54
    &x[2] = 20d58, x+2 = 20d58
    &x[3] = 20d5c, x+3 = 20d5c
    &x[4] = 20d60, x+4 = 20d60
    &x[5] = 20d64, x+5 = 20d64
    &x[6] = 20d68, x+6 = 20d68
    &x[7] = 20d6c, x+7 = 20d6c
    &x[8] = 20d70, x+8 = 20d70
    &x[9] = 20d74, x+9 = 20d74

    And p, initialized to point at x + 1, has the
    same value as the correctly aligned &x[1] above:
    p = 20d54
    Martin Ambuhl, Jun 19, 2005
  15. Pavel A.

    Chris Torek Guest

    [the magic number came from elsewhere; all Martin Ambuhl did was
    move it to a #define.]

    It is worth noting here that "x" now points to ten *bytes*, not
    ten "unsigned int"s. If sizeof(unsigned int) is 2, this is five
    "unsigned int"s; if sizeof(unsigned int) is 4, this is two with
    two leftover bytes; and if sizeof(unsigned int) is 8, this is one
    unsigned int, with two leftover bytes again. Only in the case when
    sizeof(unsigned int) == 1 -- which is probably not supported by
    GCC, although this does occur on some standalone implementations
    -- is it ten unsigned ints.

    Of course, it is true that sometimes one must deal with "misaligned"
    memory, in places like network drivers (Ethernet headers are,
    inconveniently, 14 bytes instead of 16). But there are ways to
    deal with this without ever using a single line of nonstandard C.
    Sometimes -- perhaps even "often" or "usually" -- the portability
    gain of doing byte-at-a-time arithmetic to work with 16 and 32 bit
    values outweighs the (usually tiny) performance gain one can obtain
    using a compiler's "special features" for accessing unaligned value.
    (The only way to find out for sure, of course, is to do both,
    and measure.)
    Chris Torek, Jun 19, 2005
  16. Oh crap. Thank you.
    Martin Ambuhl, Jun 19, 2005
  17. I actually forgot the definition of f :-(

    void f(UInt32 * p)
    UInt64 * q = (UInt64 *) p ;

    *q = 1234ULL ;

    return ;

    with UInt64 typedef'd in the obvious way. Isn't there an unaligned access
    on q now?
    Thomas Carter, Jun 20, 2005
  18. Yes, now there is. However, that code is now wrong, or at least
    assumes that the caller passes a pointer to UInt64 without requiring
    the caller to do so (which is a bad idea(TM)).

    You claimed that such code is common (it isn't and it's obviously
    broken) and that you've found such code in OpenSSL (did you?).

    Paul Pluzhnikov, Jun 20, 2005
  19. I admit to being carried away in my assessment here :-( My apologies.
    Here is the case I have in mind:

    A certain library uses char * throughout, with arbitrary alignments.
    Since a char will be 1 byte long (at least, in general, I believe) such
    pointers can have any alignment. Now if we have a low-level function that,
    for performance reasons, and for a particular architecture, manipulates
    unsigned int * as input, then we have a potential problem.

    The code above, while obviously wrong, attempts to illustrate such case.
    Thomas Carter, Jun 20, 2005
    1. Advertisements

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.