Typecasting pointers

Discussion in 'C Programming' started by Nishu, Jan 29, 2007.

  1. Nishu

    Nishu Guest

    Hi All,

    Is it valid in C to typecast a pointer?

    eg. code snippet... considering int as 16 bit and long as 32 bit.

    int *variable, value;

    *((long*)variable)++ = value;
    *((long*)variable)++ = value;
    *((long*)variable)++ = value;
    *((long*)variable)++ = value;

    Thanks,
    Nishu
    Nishu, Jan 29, 2007
    #1
    1. Advertising

  2. Nishu wrote:
    > Hi All,
    >
    > Is it valid in C to typecast a pointer?


    If alignment requirements are met, then yes. However, with a few
    exceptions, all you are allowed to do with the result is convert it
    back to the original type.

    > eg. code snippet... considering int as 16 bit and long as 32 bit.
    >
    > int *variable, value;
    >
    > *((long*)variable)++ = value;
    > *((long*)variable)++ = value;
    > *((long*)variable)++ = value;
    > *((long*)variable)++ = value;


    This is not allowed. Even when you are able to convert 'variable' to a
    pointer-to-long, you may not use this pointer to access anything that
    isn't really a long.
    =?utf-8?B?SGFyYWxkIHZhbiBExLNr?=, Jan 29, 2007
    #2
    1. Advertising

  3. Nishu

    Nishu Guest

    On Jan 29, 2:59 pm, "Harald van Dijk" <> wrote:
    > Nishu wrote:
    > > Hi All,

    >
    > > Is it valid in C to typecast a pointer?If alignment requirements are met, then yes. However, with a few

    > exceptions, all you are allowed to do with the result is convert it
    > back to the original type.
    >
    > > eg. code snippet... considering int as 16 bit and long as 32 bit.

    >
    > > int *variable, value;

    >
    > > *((long*)variable)++ = value;
    > > *((long*)variable)++ = value;
    > > *((long*)variable)++ = value;
    > > *((long*)variable)++ = value;This is not allowed. Even when you are able to convert 'variable' to a

    > pointer-to-long, you may not use this pointer to access anything that
    > isn't really a long.


    In case value is long...
    long value;

    I'm getting warnings on my compiler.."objects that have been cast are
    not l-value."

    Thanks,
    Nishu
    Nishu, Jan 29, 2007
    #3
  4. "Nishu" <> writes:

    > On Jan 29, 2:59 pm, "Harald van Dijk" <> wrote:
    >> Nishu wrote:
    >> > Hi All,

    >>
    >> > Is it valid in C to typecast a pointer?If alignment requirements are met, then yes. However, with a few

    >> exceptions, all you are allowed to do with the result is convert it
    >> back to the original type.
    >>
    >> > eg. code snippet... considering int as 16 bit and long as 32 bit.

    >>
    >> > int *variable, value;

    >>
    >> > *((long*)variable)++ = value;
    >> > *((long*)variable)++ = value;
    >> > *((long*)variable)++ = value;
    >> > *((long*)variable)++ = value;

    >> This is not allowed. Even when you are able to convert 'variable' to a
    >> pointer-to-long, you may not use this pointer to access anything that
    >> isn't really a long.

    >
    > In case value is long...
    > long value;
    >
    > I'm getting warnings on my compiler.."objects that have been cast are
    > not l-value."


    Take out the UB caused by the cast to long * by replacing it with int *
    and you should get the same message. It describes exactly and
    succinctly what is wrong. The result of a cast is not an lvalue -- it
    never denotes an object that can be changed. In your case,

    *((int *)variable)++

    would try to increment something, but the result of a cast is never a
    thing that can be incremented, no matter what the type is used in the
    cast. You should get the message from the more obvious:

    int x;
    ((int)x)++; /* error... casts do not make lvalues */

    --
    Ben.
    Ben Bacarisse, Jan 29, 2007
    #4
  5. Nishu

    Chris Dollin Guest

    Nishu wrote:

    > Is it valid in C to typecast a pointer?


    Aside: it's not "typecast". It's just "cast".

    --
    Chris "electric hedgehog" Dollin
    "Who do you serve, and who do you trust?" /Crusade/
    Chris Dollin, Jan 29, 2007
    #5
  6. Nishu said:

    > Hi All,
    >
    > Is it valid in C to typecast a pointer?


    It's rarely wise, and often not valid.

    > eg. code snippet... considering int as 16 bit and long as 32 bit.
    >
    > int *variable, value;
    >
    > *((long*)variable)++ = value;


    Let's count the problems.

    Firstly, value is indeterminate, so you can't use its value legitimately.
    The behaviour is undefined if you try.

    Secondly, even if that weren't a problem, variable is indeterminate, so you
    can't use its value legitimately. The behaviour is undefined if you try.

    Thirdly, even if those weren't problems, variable is an int *, and (if its
    value isn't indeterminate or a null pointer) it points to an int object,
    which may not be aligned correctly for a long int.

    Fourthly, even if those weren't problems, a cast-expression such as
    (long *)variable yields a value, not an object, and you can't use ++ on a
    mere value. It requires an object.

    Sort out those problems and then ask again.

    --
    Richard Heathfield
    "Usenet is a strange place" - dmr 29/7/1999
    http://www.cpax.org.uk
    email: rjh at the above domain, - www.
    Richard Heathfield, Jan 29, 2007
    #6
  7. Nishu

    Nishu Guest

    On Jan 29, 4:18 pm, Richard Heathfield <> wrote:
    > Nishu said:
    >
    > > Hi All,

    >
    > > Is it valid in C to typecast a pointer?It's rarely wise, and often not valid.

    >
    > > eg. code snippet... considering int as 16 bit and long as 32 bit.

    >
    > > int *variable, value;

    >
    > > *((long*)variable)++ = value;Let's count the problems.

    >


    > Sort out those problems and then ask again.


    Hi,
    I want to cast my 16bit pointer as 32 bit pointer for copying
    operation, after that i need 16bit pointer operations only. here's the
    test version of what I need to do..

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

    int main(void)
    {
    unsigned short value;
    long lvalue;

    short *ptr, *ptr1;

    ptr = (short*) malloc(sizeof(short) * 8);

    ptr1 = ptr;
    value = 0xFFF0;

    lvalue = (unsigned short)value | ((unsigned short)value << 16);

    *((long*)ptr)++ = lvalue; /* is it portable? */
    *((long*)ptr)++ = lvalue;
    *((long*)ptr)++ = lvalue;
    *((long*)ptr)++ = lvalue;

    free (ptr1);
    return 0;
    }


    MSVC doesn't give error here, but I'm doubtful about its portability.
    Please help me about other possible loop holes too.

    Thanks,
    Nishu
    Nishu, Jan 29, 2007
    #7
  8. Nishu

    Nishu Guest

    On Jan 29, 4:46 pm, "Nishu" <> wrote:
    >Hi,
    > I want to cast my 16bit pointer as 32 bit pointer for copying
    > operation, after that i need 16bit pointer operations only. here's the
    > test version of what I need to do..
    >


    here's lil' correction... and one more doubt.

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

    int main(void)
    {
    short value; /* it is signed actually*/
    long lvalue;

    short *ptr, *ptr1;

    ptr = malloc(sizeof(short) * 8);

    ptr1 = ptr;
    value = 0xFFF0; /* i get warning here. I don't understand why.
    warning is
    '=' : truncation from 'const int ' to 'short' */

    lvalue = (unsigned short)value | ((unsigned short)value << 16);

    *((long*)ptr)++ = lvalue;
    *((long*)ptr)++ = lvalue;
    *((long*)ptr)++ = lvalue;
    *((long*)ptr)++ = lvalue;

    free (ptr1);
    return 0;
    }

    Thanks,
    Nishu
    Nishu, Jan 29, 2007
    #8
  9. Nishu

    Chris Dollin Guest

    Nishu wrote:

    > On Jan 29, 4:46 pm, "Nishu" <> wrote:
    >>Hi,
    >> I want to cast my 16bit pointer as 32 bit pointer for copying
    >> operation,


    /Why/ do you want to do this bizarre thing?

    >> after that i need 16bit pointer operations only. here's the
    >> test version of what I need to do..
    >>

    >
    > here's lil' correction... and one more doubt.
    >
    > #include<stdio.h>
    > #include<stdlib.h>
    >
    > int main(void)
    > {
    > short value; /* it is signed actually*/
    > long lvalue;
    >
    > short *ptr, *ptr1;
    >
    > ptr = malloc(sizeof(short) * 8);


    Better is likely to be:

    ptr = malloc( 8 * sizeof( *ptr ) );

    If you want 8 things. (Below, it looks like you might really
    want 4).

    > ptr1 = ptr;
    > value = 0xFFF0; /* i get warning here. I don't understand why.
    > warning is
    > '=' : truncation from 'const int ' to 'short' */


    Well, yes. You say your `short`s are 16 bits. 0xFFF0 is a positive
    value (there are no negative literals),and it's an `int`. It won't fit
    into a signed short. Your compiler is warning you that you're trying
    to stuff an `int` into a `short` and that you may well have lost
    information. (Opinions about the values of such a message vary.)

    > lvalue = (unsigned short)value | ((unsigned short)value << 16);


    Why not declare `value` as an `unsigned short`, since that's all you
    ever use it as? Come to that, why not assign a literal directly to
    `lvalue` and not bother with `value` at all?

    > *((long*)ptr)++ = lvalue;
    > *((long*)ptr)++ = lvalue;
    > *((long*)ptr)++ = lvalue;
    > *((long*)ptr)++ = lvalue;


    Similarly, if what you want to do is assign to successive `long`s
    starting at the mallocated address, why not do the obvious, which
    is

    long *ptr = malloc( 4 * sizeof( *ptr ) );
    ...
    *ptr++ = lvalue;
    *ptr++ = lvalue;
    *ptr++ = lvalue;
    *ptr++ = lvalue;

    or even (having declared `int i`):

    for (i = 0; i < 4; i += 1) ptr = lvalue;

    > free (ptr1);
    > return 0;
    > }


    I don't think you're telling us everything you need to.

    --
    Chris "electric hedgehog" Dollin
    "It took a very long time, much longer than the most generous estimates."
    - James White, /Sector General/
    Chris Dollin, Jan 29, 2007
    #9
  10. Nishu

    Kelly Guest

    Nishu wrote:
    >
    > On Jan 29, 4:46 pm, "Nishu" <> wrote:
    >> Hi,
    >> I want to cast my 16bit pointer as 32 bit pointer for copying
    >> operation, after that i need 16bit pointer operations only. here's the
    >> test version of what I need to do..
    >>

    >
    > here's lil' correction... and one more doubt.
    >
    > #include<stdio.h>
    > #include<stdlib.h>
    >
    > int main(void)
    > {
    > short value; /* it is signed actually*/
    > long lvalue;
    >
    > short *ptr, *ptr1;
    >
    > ptr = malloc(sizeof(short) * 8);
    >
    > ptr1 = ptr;
    > value = 0xFFF0; /* i get warning here. I don't understand why.
    > warning is
    > '=' : truncation from 'const int ' to 'short' */
    >
    > lvalue = (unsigned short)value | ((unsigned short)value << 16);
    >
    > *((long*)ptr)++ = lvalue;
    > *((long*)ptr)++ = lvalue;
    > *((long*)ptr)++ = lvalue;
    > *((long*)ptr)++ = lvalue;
    >
    > free (ptr1);
    > return 0;
    > }
    >
    > Thanks,
    > Nishu
    >

    1>------ Build started: Project: Test, Configuration: Debug Win32 ------
    1>Compiling...
    1>test.c
    1>c:\visual studio 2005\projects\test\test\test.c(43) : warning C4213:
    nonstandard extension used : cast on l-value
    1>c:\visual studio 2005\projects\test\test\test.c(44) : warning C4213:
    nonstandard extension used : cast on l-value
    1>c:\visual studio 2005\projects\test\test\test.c(45) : warning C4213:
    nonstandard extension used : cast on l-value
    1>c:\visual studio 2005\projects\test\test\test.c(46) : warning C4213:
    nonstandard extension used : cast on l-value
    1>c:\visual studio 2005\projects\test\test\test.c(43) : *warning C6011:
    Dereferencing NULL pointer '((long *)ptr)++': Lines: 29, 30, 32, 34, 36,
    37, 41, 43*

    Looks ominous to me!

    1>Linking...
    1>Embedding manifest...
    1>Test - 0 error(s), 5 warning(s)
    ========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========
    Kelly, Jan 29, 2007
    #10
  11. "Nishu" <> writes:
    > On Jan 29, 4:46 pm, "Nishu" <> wrote:
    > > I want to cast my 16bit pointer as 32 bit pointer for copying
    > > operation, after that i need 16bit pointer operations only. here's the
    > > test version of what I need to do..
    > >

    >
    > here's lil' correction... and one more doubt.


    Ok, I think I see what you're trying to do. You want to create an
    array of shorts, and initialize them all to the same value. If it
    were an array of bytes memset() would be just the thing, but there's
    no standard routine that does for shorts what memset() does for bytes.

    You're assuming that short is 16 bits and long is 32 bits. Be aware
    that these assumptions are *not* portable. If you're willing to live
    with the fact that your code will break, perhaps quietly, on some
    systems, you should at least document your assumptions.

    > #include<stdio.h>
    > #include<stdlib.h>
    >
    > int main(void)
    > {
    > short value; /* it is signed actually*/


    Why is it signed? For what you're doing, using unsigned types would
    be simpler -- ahd the value 0xFFF0 won't fit into a 16-bit unsigned
    object.

    > long lvalue;


    "lvalue" turns out to be a poor name for this variable. I understand
    that you meant it to be an abbreviation for "long value", but in C the
    term "lvalue" has a specific meaning (roughly, it's an expression that
    designates an object).

    > short *ptr, *ptr1;


    Again, unsigned short would probably serve your purposes better.

    > ptr = malloc(sizeof(short) * 8);


    Thank you for not casting the result of malloc(), but an even better
    way to write this is:

    ptr = malloc(8 * sizeof *ptr);

    And you should *always* check the result of malloc().

    > ptr1 = ptr;


    You're saving the value of ptr so you can free() it later. That's
    good, but see below for a comment on this.

    > value = 0xFFF0; /* i get warning here. I don't understand why.
    > warning is
    > '=' : truncation from 'const int ' to 'short' */


    The maximum value of signed short on your system is 0x7FFF; that's
    what your compiler is warning you about.

    > lvalue = (unsigned short)value | ((unsigned short)value << 16);


    If you declare value as an unsigned short, you don't need the casts.

    > *((long*)ptr)++ = lvalue;
    > *((long*)ptr)++ = lvalue;
    > *((long*)ptr)++ = lvalue;
    > *((long*)ptr)++ = lvalue;


    This is the core of what you're doing, and of your problem.

    You're initializing an array of 2-byte integers, but you're trying to
    do it 4 bytes at a time, presumably because you think it will be
    faster (more on that later). In general, this is a dangerous thing to
    do, because there's no guarantee that an array of shorts will be
    properly aligned as an array of longs. In this case, you happen to be
    ok, because malloc() returns a result suitably aligned for any type.
    If you're thinking of using this as a general technique, alignment
    will eventually come back and bite you. You should also think about
    the case where the length of the array is odd.

    The "++" operator modifies an object. It can't be applied to
    something that isn't an object -- specifically, it requires an lvalue,
    an expression that designates an object. A cast yields a converted
    *value*; it doesn't refer to any object. So applying "++" to the
    result of a cast makes no more sense than assigning to the result of
    "+":

    int x;
    (x + 2) = 4; /* illegal, (x + 2) is not an lvalue */

    (The language *could* conceivably have defined reasonable semantics
    for treating the result of a cast as an lvalue, but it didn't, and
    we're stuck with that.)

    A pointer increment advances the pointer by one object size,
    specifically the size of the object to which it points. You want to
    advance ptr by the size of a long, but it's declared to point to a
    short. Casting the pointer *value* and incrementing it is, as
    discussed above, illegal.

    What you really want to do is take the value of ptr (of type short*),
    convert it to long*, add 1 to the resulting *value*, and convert the
    result back to short*:
    ptr = (short*)((long*)ptr + 1);
    Or you can just use the knowledge (well, assumption) that a long is
    twice the size of a short, and simply do this:
    ptr += 2;

    Now this isn't something you can easily do as a side effect of your
    assignment statement, but so what? Extreme terseness isn't always a
    virtue. Do the assignment, then increment the pointer:

    *((long*)ptr) = lvalue;
    ptr += 2;
    *((long*)ptr) = lvalue;
    ptr += 2;
    *((long*)ptr) = lvalue;
    ptr += 2;
    *((long*)ptr) = lvalue;

    And we've dropped the final increment, since we're not using the value
    of ptr again.

    > free (ptr1);
    > return 0;
    > }


    An outline of what you've done with memory allocation is:

    ptr = malloc(...);
    ptr1 = ptr;
    /* manipulate ptr */
    free(ptr1);

    This is perfectly correct, but just as a matter of style you might
    consider manipulating the *copy* of ptr rather than ptr itself. This
    makes for greater symmetry (ptr = malloc(...); ... free(ptr);). You
    can even declare ptr as const to make (reasonably) sure you don't
    accidentally clobber it.

    Now let's zoom back and look at what you're trying to do.

    Except in performance-critical code, it's usually best to write the
    most straightforward possible code, and let the compiler optimize it
    as well as it can. In your program, you write a considerable amount
    of extra code to initialize your array 4 bytes at a time rather than 2
    bytes at a time, and you've unrolled the initialization loop (writing
    four separate assignments rather than a single one in a loop). Either
    or both of these *might* make your code a little faster -- or they
    might not. By making your code more complex, you may have made it
    more difficult for the optimizer to analyze; conceivably a good
    optimizing compiler could have done a better job than you have. And,
    by trying to be fancy, you've gotten the code wrong, which has cost
    you many orders of magnitude more of your own time than the CPU time
    you might have saved.

    Once you get your code working, try measuring the *actual* time spent;
    you may find that the improvement is either nonexistent, or just not
    worth the effort.

    Or you just might find that it's significant, that the code is in an
    inner loop in a performance-critical application, and that this was
    all worth it. Or it could be worthwhile just as a learning
    experience.

    If you do want to do this optimization, there are easier ways to go
    about it. You can treat the whole array as an array of unsigned longs
    and initialize it that way, rather than converting pointers on each
    iteration.

    Here's a simplified version of your program. I've removed the
    optimizations, but I've added some error checking.
    ================================
    #include <stdio.h> /* This isn't actually used */
    #include <stdlib.h>
    int main(void)
    {
    #define COUNT 8
    #define INIT 0xFFF0

    unsigned short value;
    unsigned short *const ptr = malloc(COUNT * sizeof *ptr);
    int i;

    if (ptr == NULL) {
    fprintf(stderr, "malloc() failed\n");
    exit(EXIT_FAILURE);
    }

    for (i = 0; i < COUNT; i ++) {
    ptr = INIT;
    }

    free (ptr);
    return 0;
    }
    ================================

    And here's another version with optimization. I've unrolled the loop
    as you did, and I've used a pointer rather than an integer index to
    access the array. (It's tempting to assume that pointer accesses will
    be faster than indexing, but it's not necesarily the case -- and an
    optimizing compiler can often tranform one to the other.)

    One note here. I've defined COUNT as a macro rather than using the
    "magic number" 8. The idea is that you can change the definition of
    COUNT if necessary without touching the rest of the program. For the
    unoptimized version above, that works. For the optimized version
    below, it doesn't; the number of assignment statements needs to be
    COUNT/2 (and COUNT needs to be even), but if you change the definition
    of COUNT you also need to manually update the unrolled loop.

    ================================
    #include <stdio.h>
    #include <stdlib.h>
    #include <assert.h>
    int main(void)
    {
    /*
    * We require long to be twice the size of short.
    * We'll check this with an assert(); if it's not the case,
    * we don't even want the program to run.
    */

    #define COUNT 8
    #define INIT 0xFFF0
    #define INIT_TWICE (((unsigned long)INIT << 16) | (unsigned long)INIT)

    unsigned short value;
    unsigned short *const ptr = malloc(COUNT * sizeof *ptr);
    unsigned long *lptr;

    assert(sizeof(short) * 2 == sizeof(long));

    if (ptr == NULL) {
    fprintf(stderr, "malloc() failed\n");
    exit(EXIT_FAILURE);
    }

    lptr = (unsigned long*)ptr;
    *lptr++ = INIT_TWICE;
    *lptr++ = INIT_TWICE;
    *lptr++ = INIT_TWICE;
    *lptr = INIT_TWICE;

    free (ptr);
    return 0;
    }
    ================================

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    We must do something. This is something. Therefore, we must do this.
    Keith Thompson, Jan 29, 2007
    #11
  12. "Nishu" <> wrote in message
    news:...
    > Hi All,
    >
    > Is it valid in C to typecast a pointer?
    >
    > eg. code snippet... considering int as 16 bit and long as 32 bit.
    >
    > int *variable, value;
    >
    > *((long*)variable)++ = value;
    > *((long*)variable)++ = value;
    > *((long*)variable)++ = value;


    In type-casting a pointer, all you do is change the way the compiler treats
    it in two contexts:

    a)Array indexing and incrementing/decrementing (the compiler has to know how
    large the data pointed to is in order to know how to index or advance a
    pointer).

    b)Variable/structure references using the pointer.

    Where program space is critical (small embedded work), one finds all sorts
    of tricks with unions and pointers to get the compiler to behave in the
    desired way.

    But in a larger system (such as an x86 box), there really aren't any
    contexts where one needs to do this. If you have to go that low ... better
    to write certain modules in assembly-language than to abuse the compiler in
    ways which may become invalid with a compiler version or platform change.

    --
    David T. Ashley ()
    http://www.e3ft.com (Consulting Home Page)
    http://www.dtashley.com (Personal Home Page)
    http://gpl.e3ft.com (GPL Publications and Projects)
    David T. Ashley, Jan 29, 2007
    #12
  13. In article <>,
    David T. Ashley <> wrote:

    >In type-casting a pointer, all you do is change the way the compiler treats
    >it in two contexts:


    >a)Array indexing and incrementing/decrementing (the compiler has to know how
    >large the data pointed to is in order to know how to index or advance a
    >pointer).


    >b)Variable/structure references using the pointer.


    If the pointer is cast to a type with a stricter alignment requirement
    and then cast back again, the twice-cast pointer need not be valid.
    (However, if a pointer is cast to a type with the same strictness or
    less strict alignment, it may be cast back and is promised to compare
    equal to the original.)

    We can see from this that the actual representation can
    irreversibly change when a pointer is cast to another type.
    There can also be changes to such things as base segment and
    offset when a pointer is cast -- some systems allow multiple
    representations for the same pointer.

    All in all, it can get more complicated internally than you imply
    by saying that "all you do is change the way the compiler treats
    it in two contexts."

    --
    "No one has the right to destroy another person's belief by
    demanding empirical evidence." -- Ann Landers
    Walter Roberson, Jan 29, 2007
    #13
  14. "David T. Ashley" <> writes:
    > "Nishu" <> wrote in message
    > news:...
    > > Is it valid in C to typecast a pointer?
    > >
    > > eg. code snippet... considering int as 16 bit and long as 32 bit.
    > >
    > > int *variable, value;
    > >
    > > *((long*)variable)++ = value;
    > > *((long*)variable)++ = value;
    > > *((long*)variable)++ = value;

    >
    > In type-casting a pointer, all you do is change the way the compiler treats
    > it in two contexts:
    >
    > a)Array indexing and incrementing/decrementing (the compiler has to know how
    > large the data pointed to is in order to know how to index or advance a
    > pointer).
    >
    > b)Variable/structure references using the pointer.

    [...]

    Casting (not "type-casting") a pointer converts its value to some
    specified type, yielding a value of the new type. For a
    pointer-to-pointer conversion, the result may or may not be a valid,
    depending on a number of factors, some defined by the standard, some
    implementation-defined.

    For example, converting an object pointer to type unsigned char*
    always gives you a valid result (assuming the original value is valid)
    and allows you to access the representation of the pointed-to object.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    We must do something. This is something. Therefore, we must do this.
    Keith Thompson, Jan 29, 2007
    #14
  15. Nishu

    pete Guest

    Walter Roberson wrote:

    > If the pointer is cast to a type with a stricter alignment requirement
    > and then cast back again, the twice-cast pointer need not be valid.


    The first cast pointer need not be valid either.

    char array[sizeof(int) + 1];

    *(int *)(array + 1) = 0;

    --
    pete
    pete, Jan 30, 2007
    #15
  16. "Walter Roberson" <-cnrc.gc.ca> wrote in message
    news:eplral$364$...
    > In article <>,
    > David T. Ashley <> wrote:
    >
    > (However, if a pointer is cast to a type with the same strictness or
    > less strict alignment, it may be cast back and is promised to compare
    > equal to the original.)


    Is that a personal observation or part of a standard?

    --
    David T. Ashley ()
    http://www.e3ft.com (Consulting Home Page)
    http://www.dtashley.com (Personal Home Page)
    http://gpl.e3ft.com (GPL Publications and Projects)
    David T. Ashley, Jan 30, 2007
    #16
  17. In article <>,
    David T. Ashley <> wrote:
    >"Walter Roberson" <-cnrc.gc.ca> wrote in message
    >news:eplral$364$...
    >> In article <>,
    >> David T. Ashley <> wrote:
    >>
    >> (However, if a pointer is cast to a type with the same strictness or
    >> less strict alignment, it may be cast back and is promised to compare
    >> equal to the original.)


    >Is that a personal observation or part of a standard?


    ANSI X.3-159

    3.3.4 Cast Operators
    [...]
    A pointer to an object or incomplete type may be converted to
    a pointer to a different object type or a different incomplete
    type. The resulting pointer might not be valid if it is
    improperly aligned for the type pointed to. It is guaranteed,
    however, that a pointer to an object of a given alignment
    may be converted to a pointer to an object of the same
    alignment or a less strict alignment and back again; the result
    shall compare equal to the original pointer. (An object
    that has character type has the least strict alignment.)
    --
    If you lie to the compiler, it will get its revenge. -- Henry Spencer
    Walter Roberson, Jan 30, 2007
    #17
  18. "Walter Roberson" <-cnrc.gc.ca> wrote in message
    news:epm86p$jj3$...
    > In article <>,
    > David T. Ashley <> wrote:
    >>"Walter Roberson" <-cnrc.gc.ca> wrote in message
    >>news:eplral$364$...
    >>> In article <>,
    >>> David T. Ashley <> wrote:
    >>>
    >>> (However, if a pointer is cast to a type with the same strictness or
    >>> less strict alignment, it may be cast back and is promised to compare
    >>> equal to the original.)

    >
    >>Is that a personal observation or part of a standard?

    >
    > ANSI X.3-159
    >
    > 3.3.4 Cast Operators
    > [...]
    > A pointer to an object or incomplete type may be converted to
    > a pointer to a different object type or a different incomplete
    > type. The resulting pointer might not be valid if it is
    > improperly aligned for the type pointed to. It is guaranteed,
    > however, that a pointer to an object of a given alignment
    > may be converted to a pointer to an object of the same
    > alignment or a less strict alignment and back again; the result
    > shall compare equal to the original pointer. (An object
    > that has character type has the least strict alignment.)


    Interesting.

    I've never seen a machine where simply casting a pointer to a more strict
    alignment will cause it to change its value. The trouble usually begins
    when you try to USE the casted pointer.

    But interesting that the standard only makes guarantees in one direction.

    --
    David T. Ashley ()
    http://www.e3ft.com (Consulting Home Page)
    http://www.dtashley.com (Personal Home Page)
    http://gpl.e3ft.com (GPL Publications and Projects)
    David T. Ashley, Jan 30, 2007
    #18
  19. Nishu

    Nishu Guest

    On Jan 30, 2:07 am, Keith Thompson <> wrote:
    > "Nishu" <> writes:
    > > On Jan 29, 4:46 pm, "Nishu" <> wrote:
    > > > I want to cast my 16bit pointer as 32 bit pointer for copying
    > > > operation, after that i need 16bit pointer operations only. here's the
    > > > test version of what I need to do..

    >
    > > here's lil' correction... and one more doubt.

    >


    > And here's another version with optimization. I've unrolled the loop
    > as you did, and I've used a pointer rather than an integer index to
    > access the array. (It's tempting to assume that pointer accesses will
    > be faster than indexing, but it's not necesarily the case -- and an
    > optimizing compiler can often tranform one to the other.)
    >
    > One note here. I've defined COUNT as a macro rather than using the
    > "magic number" 8. The idea is that you can change the definition of
    > COUNT if necessary without touching the rest of the program. For the
    > unoptimized version above, that works. For the optimized version
    > below, it doesn't; the number of assignment statements needs to be
    > COUNT/2 (and COUNT needs to be even), but if you change the definition
    > of COUNT you also need to manually update the unrolled loop.
    >
    > ================================
    > #include <stdio.h>
    > #include <stdlib.h>
    > #include <assert.h>
    > int main(void)
    > {
    > /*
    > * We require long to be twice the size of short.
    > * We'll check this with an assert(); if it's not the case,
    > * we don't even want the program to run.
    > */
    >
    > #define COUNT 8
    > #define INIT 0xFFF0
    > #define INIT_TWICE (((unsigned long)INIT << 16) | (unsigned long)INIT)
    >
    > unsigned short value;
    > unsigned short *const ptr = malloc(COUNT * sizeof *ptr);
    > unsigned long *lptr;
    >
    > assert(sizeof(short) * 2 == sizeof(long));
    >
    > if (ptr == NULL) {
    > fprintf(stderr, "malloc() failed\n");
    > exit(EXIT_FAILURE);
    > }
    >
    > lptr = (unsigned long*)ptr;
    > *lptr++ = INIT_TWICE;
    > *lptr++ = INIT_TWICE;
    > *lptr++ = INIT_TWICE;
    > *lptr = INIT_TWICE;
    >
    > free (ptr);
    > return 0;}
    >


    Thank you Keith and all. I'll keep these things in mind.

    Thanks,
    Nishu
    Nishu, Jan 30, 2007
    #19
  20. In article <>,
    David T. Ashley <> wrote:
    >>>"Walter Roberson" <-cnrc.gc.ca> wrote in message
    >>>news:eplral$364$...


    >>>> (However, if a pointer is cast to a type with the same strictness or
    >>>> less strict alignment, it may be cast back and is promised to compare
    >>>> equal to the original.)


    >Interesting.


    >I've never seen a machine where simply casting a pointer to a more strict
    >alignment will cause it to change its value. The trouble usually begins
    >when you try to USE the casted pointer.


    Suppose you are using a machine which has int pointers distinct
    from char pointers -- e.g., (int *)0x00a5 refers to the 166'th
    int location and (char *)0x00a5 refers to the 166'th char location.
    Suppose further that sizeof(int) == 4 and that the memory fields
    overlap, so (int *)0x00a5 is the same memory location as
    (char *)(0x00a5*sizeof(int)) = (char *)0x0294. [According to some
    previous postings, similar machines exist and are actually used.]

    In this situation, to convert an int* to the less strict alignment, you
    multiply the int* address by sizeof(int) to get the equivilent (char *)
    address. If one then convers that (char *) back to (int *), divide the
    (char *) memory address by sizeof(int) and (int *)0x00a5 is recovered.

    Now try that the other way around, converting (char *)0x00a5 to
    an (int *). Divide the (char *) memory address by sizeof(int)
    to get (int *)0x0029; cast back by multiplying by sizeof(int)
    to get (char *)0x00a4 . Oh-oh, that's not the original (char *) address!

    Hence, casting a pointer can change its value, and casting to
    a stricter alignment and back can result in something that doesn't
    point to the original location.
    --
    Prototypes are supertypes of their clones. -- maplesoft
    Walter Roberson, Jan 30, 2007
    #20
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. brian

    Typecasting Pointers

    brian, Nov 23, 2004, in forum: C Programming
    Replies:
    13
    Views:
    1,271
    Michael Wojcik
    Nov 29, 2004
  2. Replies:
    3
    Views:
    592
    Emmanuel Delahaye
    Jul 15, 2005
  3. typecasting of function pointers

    , Mar 20, 2006, in forum: C Programming
    Replies:
    12
    Views:
    922
    Flash Gordon
    Mar 21, 2006
  4. Replies:
    12
    Views:
    598
    Stephen Sprunk
    Aug 8, 2006
  5. Quentin Pope

    Typecasting Pointers on a 64 bit System

    Quentin Pope, Nov 10, 2011, in forum: C Programming
    Replies:
    54
    Views:
    1,523
    Phil Carmody
    Nov 18, 2011
Loading...

Share This Page