CAN WE TYPE CAST AN INTEGER AS (VOID *)X..(Like can I return a value (void *)x)

Discussion in 'C Programming' started by Abhishek, Jan 29, 2006.

  1. Abhishek

    Abhishek Guest

    now suppose I have declared an integer value inside a function as
    int x;
    now if the return type of the function is of type (void *) then can I
    write
    return((void *)x) in side the function?
    I came across this in a document on multithreading in C..I can post the
    exact portion of code which works correctly with such an assignment if
    you people want.
    Please clarify my doubt.I hope I have conveyed it properly.
     
    Abhishek, Jan 29, 2006
    #1
    1. Advertising

  2. Abhishek

    Ico Guest

    Hello Abhishek,

    Please do not write sentences in ALL UPPERCASE. This will only cause
    people to ignore your posts, since this is a style which is often used
    by spammers. Also, try to keep your subject short, since some people
    might be using newsreaders which are not able to display too long
    subject lines. A good subject for your post might have been something
    like "Casting int to void *"

    Abhishek <> wrote:

    > now suppose I have declared an integer value inside a function as int
    > x; now if the return type of the function is of type (void *) then can
    > I write return((void *)x) in side the function?


    Yes, this is possible, but I suspect this might result in undefined
    behaviour. By casting an int to a void pointer, you take the number in
    x, and convert it to an address. You are telling your compiler `trust
    me, I know what I am doing. Although this is just a regular number, I am
    sure this number is a valid address of something which doesn't have a
    specific type'. This might or might not work on your platform, since
    there is no guarantee that an int might fit into a pointer. I am not
    aware of any good reasons for using an integer type to store a pointer,
    although I am aware of other code where this is common practice (the
    Linux kernel). Maybe somebody else can explain why this is done.

    Ico

    --
    :wq
    ^X^Cy^K^X^C^C^C^C
     
    Ico, Jan 29, 2006
    #2
    1. Advertising

  3. Ico wrote:

    > Hello Abhishek,
    >
    > Please do not write sentences in ALL UPPERCASE. This will only cause
    > people to ignore your posts, since this is a style which is often used
    > by spammers.


    I must say, my immediate reaction to ALL CAPS tends to be STOP
    SHOUTING! ;-)

    <snipped more good advice>

    > Abhishek <> wrote:
    >
    >> now suppose I have declared an integer value inside a function as int
    >> x; now if the return type of the function is of type (void *) then
    >> can
    >> I write return((void *)x) in side the function?

    >
    > Yes, this is possible, but I suspect this might result in undefined
    > behaviour. By casting an int to a void pointer, you take the number in
    > x, and convert it to an address. You are telling your compiler `trust
    > me, I know what I am doing. Although this is just a regular number, I
    > am sure this number is a valid address of something which doesn't have
    > a specific type'. This might or might not work on your platform, since
    > there is no guarantee that an int might fit into a pointer. I am not
    > aware of any good reasons for using an integer type to store a
    > pointer, although I am aware of other code where this is common
    > practice (the Linux kernel). Maybe somebody else can explain why this
    > is done.


    This is certainly undefined behaviour, if not worse. Once you return
    from the function, as far a C Standard is concerned, all objects local
    to that function _cease_to_exist_ (as was mentioned elsewhere in c.l.c,
    Standard knows nothing about stacks and similar real world concepts).
    Referring to them outside the function should really make your head
    spin. ;-)

    Of course, an implementation is allowed to take shortcuts by not
    bothering to physically destroy such objects, and so you may not get
    illegal access or whatever error is appropriate. However, even changing
    optimisation level, let alone the whole compiler may make your (OP's)
    code behave in a totally different way.

    Cheers

    Vladimir

    Cheers

    Vladimir

    --
    "We are upping our standards ... so up yours."
    -- Pat Paulsen for President, 1988.
     
    Vladimir S. Oka, Jan 29, 2006
    #3
  4. Abhishek

    Ico Guest

    Vladimir S. Oka <> wrote:
    > Ico wrote:
    >
    >> Hello AbhishV00ek,
    >>
    >> Abhishek <> wrote:
    >>
    >>> now suppose I have declared an integer value inside a function as int
    >>> x; now if the return type of the function is of type (void *) then
    >>> can
    >>> I write return((void *)x) in side the function?

    >>
    >> Yes, this is possible, but I suspect this might result in undefined
    >> behaviour. By casting an int to a void pointer, you take the number in
    >> x, and convert it to an address. You are telling your compiler `trust
    >> me, I know what I am doing. Although this is just a regular number, I
    >> am sure this number is a valid address of something which doesn't have
    >> a specific type'. This might or might not work on your platform, since
    >> there is no guarantee that an int might fit into a pointer. I am not
    >> aware of any good reasons for using an integer type to store a
    >> pointer, although I am aware of other code where this is common
    >> practice (the Linux kernel). Maybe somebody else can explain why this
    >> is done.

    >
    > This is certainly undefined behaviour, if not worse. Once you return
    > from the function, as far a C Standard is concerned, all objects local
    > to that function _cease_to_exist_ (as was mentioned elsewhere in c.l.c,
    > Standard knows nothing about stacks and similar real world concepts).
    > Referring to them outside the function should really make your head
    > spin. ;-)
    >
    > Of course, an implementation is allowed to take shortcuts by not
    > bothering to physically destroy such objects, and so you may not get
    > illegal access or whatever error is appropriate. However, even changing
    > optimisation level, let alone the whole compiler may make your (OP's)
    > code behave in a totally different way.


    Vladimir, I think you misread the details in the OP's question: as far
    as I onderstood, he is not returning the address of x, but the *value*
    of x, casted to void * :

    >>> return((void *)x)


    Apart from the cast, this is just as valid as returning x intself.

    Ico

    --
    :wq
    ^X^Cy^K^X^C^C^C^C
     
    Ico, Jan 29, 2006
    #4
  5. Abhishek

    Eric Sosman Guest

    Re: CAN WE TYPE CAST AN INTEGER AS (VOID *)X..(Like can I returna value (void *)x)

    Vladimir S. Oka wrote:
    > Ico wrote:
    >
    >
    >>Hello Abhishek,
    >>
    >>Please do not write sentences in ALL UPPERCASE. This will only cause
    >>people to ignore your posts, since this is a style which is often used
    >>by spammers.

    >
    >
    > I must say, my immediate reaction to ALL CAPS tends to be STOP
    > SHOUTING! ;-)
    >
    > <snipped more good advice>
    >
    >
    >>Abhishek <> wrote:
    >>
    >>
    >>>now suppose I have declared an integer value inside a function as int
    >>>x; now if the return type of the function is of type (void *) then
    >>>can
    >>>I write return((void *)x) in side the function?

    >>
    >>Yes, this is possible, but I suspect this might result in undefined
    >>behaviour. By casting an int to a void pointer, you take the number in
    >>x, and convert it to an address. You are telling your compiler `trust
    >>me, I know what I am doing. Although this is just a regular number, I
    >>am sure this number is a valid address of something which doesn't have
    >>a specific type'. This might or might not work on your platform, since
    >>there is no guarantee that an int might fit into a pointer. I am not
    >>aware of any good reasons for using an integer type to store a
    >>pointer, although I am aware of other code where this is common
    >>practice (the Linux kernel). Maybe somebody else can explain why this
    >>is done.

    >
    >
    > This is certainly undefined behaviour, if not worse. Once you return
    > from the function, as far a C Standard is concerned, all objects local
    > to that function _cease_to_exist_ (as was mentioned elsewhere in c.l.c,
    > Standard knows nothing about stacks and similar real world concepts).
    > Referring to them outside the function should really make your head
    > spin. ;-)


    This is true, but has nothing to do with the question.

    The O.P. has run across a function whose return type is
    `void*' <ot> because of the requirements of a framework that
    is not topical here </ot>. However, in the context of the
    actual function it makes more sense to return an `int'. The
    code tries to do so by converting the `int' to a `void*';
    presumably, the caller retrieves the `void*' and converts it
    back to an `int' again. The O.P. asks whether C guarantees
    that this will work as desired.

    The answer (may I have the envelope, please?) is "No."
    An integer can be converted to any pointer type (6.3.2.3/5),
    but the result is implementation-defined. A pointer can be
    converted to an integer (6.3.2.3/6), but again the result is
    implementation-defined. It is not guaranteed that the two
    conversions are inverses; that is, it is not guaranteed that
    the number that emerges from the second conversion is the same
    value that entered the first. In fact, either or both of the
    conversions may yield trap values, and the mere act of trying
    to do something with a trap value (e.g., return it from a
    function) yields undefined behavior.

    That said, the dubious practice will in fact work as desired
    on many implementations (I suspect it might fail on AS/400, but
    I'm not sure of that). Completely portable approaches exist,
    but some programmers are too lazy or too unimaginative to use
    them. The O.P. is looking at such a programmer's product.

    --
    Eric Sosman
    lid
     
    Eric Sosman, Jan 29, 2006
    #5
  6. Abhishek

    Robin Haigh Guest

    Re: Can we cast an integer as (void *)x

    "Abhishek" <> wrote in message
    news:...
    > now suppose I have declared an integer value inside a function as
    > int x;
    > now if the return type of the function is of type (void *)
    > then can I write
    > return((void *)x) in side the function?
    > I came across this in a document on multithreading in C.



    6.3.2.3 p5 says an integer may be converted to a pointer type. The result
    is implementation-defined.

    This doesn't mean undefined behaviour: it means the implementation is
    required to make it work and tell you how.

    The document where you saw this is discussing the multithreading extension
    in a particular implementation. The code relies on other features of the
    implementation, but that doesn't make it any more non-portable than it
    already is.

    I suspect there's no intention of using the return value as a pointer. It
    probably does something like

    retp = func();
    if (retp == (void *)-1) {
    /* handle special case */
    } else {
    /* retp is a normal pointer */
    }

    This isn't as elegant as some people might like, but it's fine

    --
    RSH
     
    Robin Haigh, Jan 29, 2006
    #6
  7. Re: Can we cast an integer as (void *)x

    "Robin Haigh" <> writes:
    > "Abhishek" <> wrote in message
    > news:...
    >> now suppose I have declared an integer value inside a function as
    >> int x;
    >> now if the return type of the function is of type (void *)
    >> then can I write
    >> return((void *)x) in side the function?
    >> I came across this in a document on multithreading in C.

    >
    >
    > 6.3.2.3 p5 says an integer may be converted to a pointer type. The result
    > is implementation-defined.
    >
    > This doesn't mean undefined behaviour: it means the implementation is
    > required to make it work and tell you how.


    Right, but here's the whole of 6.3.2.3p5:

    An integer may be converted to any pointer type. Except as
    previously specified, the result is implementation-defined, might
    not be correctly aligned, might not point to an entity of the
    referenced type, and might be a trap representation.

    and a footnote:

    The mapping functions for converting a pointer to an integer or an
    integer to a pointer are intended to be consistent with the
    addressing structure of the execution environment.

    > The document where you saw this is discussing the multithreading extension
    > in a particular implementation. The code relies on other features of the
    > implementation, but that doesn't make it any more non-portable than it
    > already is.
    >
    > I suspect there's no intention of using the return value as a pointer. It
    > probably does something like
    >
    > retp = func();
    > if (retp == (void *)-1) {
    > /* handle special case */
    > } else {
    > /* retp is a normal pointer */
    > }
    >
    > This isn't as elegant as some people might like, but it's fine


    If retp happens to be a trap representation, evaluating it for the
    purpose of comparing it to (void*)-1 invokes undefined behavior. For
    that matter, assigning the result of func() to retp in the first place
    probably invokes undefined behavior.

    The code is portable only to systems on which the conversion doesn't
    yield a trap representation (which may well be all the systems on
    which the code is expected to run).

    <OFF_TOPIC>
    I think POSIX has at least one function that uses -1 converted to a
    pointer type as a special return value.
    </OFF_TOPIC>

    Let's look at the original problem. You have a function that normally
    returns a pointer value (void*), but sometimes you want an integer
    value. There are at least two cases to consider.

    If you want a single, or a small number of, distinctive values other
    than NULL, using (void*)-1 can work on many platforms, but strictly
    speaking it's non-portable (and frankly it's ugly).

    A portable solution is to declare an otherwise-unused object and use
    its address as a special value.

    If you just want to return either a pointer or a arbitrary integer
    value, then you probably have a poorly designed interface. The
    function can return a record (or a union) containing both a pointer
    and an integer, and some indication of which is valid. Or it can
    return extra information indirectly via a parameter. And so forth.

    Or if the caller can know in advance whether the result is going to be
    a pointer or an integer, perhaps there should be two separate
    functions.

    --
    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, 2006
    #7
  8. Abhishek

    Robin Haigh Guest

    Re: Can we cast an integer as (void *)x

    "Keith Thompson" <> wrote in message
    news:...
    > "Robin Haigh" <> writes:
    > > "Abhishek" <> wrote in message
    > > news:...
    > >> now suppose I have declared an integer value inside a function as
    > >> int x;
    > >> now if the return type of the function is of type (void *)
    > >> then can I write
    > >> return((void *)x) in side the function?
    > >> I came across this in a document on multithreading in C.

    > >
    > >
    > > 6.3.2.3 p5 says an integer may be converted to a pointer type. The

    result
    > > is implementation-defined.
    > >
    > > This doesn't mean undefined behaviour: it means the implementation is
    > > required to make it work and tell you how.

    >
    > Right, but here's the whole of 6.3.2.3p5:
    >
    > An integer may be converted to any pointer type. Except as
    > previously specified, the result is implementation-defined, might
    > not be correctly aligned, might not point to an entity of the
    > referenced type, and might be a trap representation.



    If you're quoting C89, you've got me, I was using the C99 draft (N869).
    This doesn't have the last bit ("and might be a trap representation").

    That's because it's meaningless. 6.3.2.3 comes under "Conversions". A
    conversion takes a value and yields a value. A value is just an
    intermediate in expression evaluation, and we know nothing about how it may
    be held, or represented in whatever it's held in. (I say "held" because it
    isn't "stored" until it's assigned to a storage object)

    A trap representation is an object representation that doesn't have a value.
    An object representation is created when a value is written into a
    byte-addressed storage object (e.g. a variable), by encoding the value into
    an ordered sequence of bytes (which are now visible, by way of a pointer
    cast). (6.2.6)

    That's still working from C99. The wording you quote from C89 seems to be
    based on a different concept of trap representation?

    --
    RSH
     
    Robin Haigh, Jan 30, 2006
    #8
  9. Re: Can we cast an integer as (void *)x

    "Robin Haigh" <> writes:
    > "Keith Thompson" <> wrote in message
    > news:...
    >> "Robin Haigh" <> writes:
    >> > "Abhishek" <> wrote in message
    >> > news:...
    >> >> now suppose I have declared an integer value inside a function as
    >> >> int x;
    >> >> now if the return type of the function is of type (void *)
    >> >> then can I write
    >> >> return((void *)x) in side the function?
    >> >> I came across this in a document on multithreading in C.
    >> >
    >> > 6.3.2.3 p5 says an integer may be converted to a pointer type.
    >> > The result is implementation-defined.
    >> >
    >> > This doesn't mean undefined behaviour: it means the implementation is
    >> > required to make it work and tell you how.

    >>
    >> Right, but here's the whole of 6.3.2.3p5:
    >>
    >> An integer may be converted to any pointer type. Except as
    >> previously specified, the result is implementation-defined, might
    >> not be correctly aligned, might not point to an entity of the
    >> referenced type, and might be a trap representation.

    >
    >
    > If you're quoting C89, you've got me, I was using the C99 draft (N869).
    > This doesn't have the last bit ("and might be a trap representation").


    No, I was quoting N1124, which includes C99 plus TC2. I just checked
    and the actual C99 standard has the same wording (and there are no
    change bars in that section in N1124). Apparently the trap
    representation wording was added between N860 and the actual standard.

    > That's because it's meaningless. 6.3.2.3 comes under "Conversions". A
    > conversion takes a value and yields a value. A value is just an
    > intermediate in expression evaluation, and we know nothing about how it may
    > be held, or represented in whatever it's held in. (I say "held" because it
    > isn't "stored" until it's assigned to a storage object)
    >
    > A trap representation is an object representation that doesn't have a value.
    > An object representation is created when a value is written into a
    > byte-addressed storage object (e.g. a variable), by encoding the value into
    > an ordered sequence of bytes (which are now visible, by way of a pointer
    > cast). (6.2.6)


    That's a good point. I think the wording I quoted is *trying* to say
    something important, but it blurs the distinction between values and
    representations (not the only place the standard does this).

    Given:

    int i = some_value;
    void *p = (void*)i;

    it seems obvious (to me) that p might have a trap representation after
    it's initialized. The alternative would be either to require void*
    not to have any trap representations, or to require implementations to
    go to heroic efforts to avoid letting conversions generate trap
    representations.

    The standard tries to cover this by saying that the value yielded by
    the conversion "might be a trap representation". I see the problem,
    but I don't know how to fix it. The simplest fix would be just to say
    that trap representations are values.

    --
    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 30, 2006
    #9
  10. Ico wrote:

    > Vladimir S. Oka <> wrote:
    >> Ico wrote:
    >>
    >>> Hello AbhishV00ek,
    >>>
    >>> Abhishek <> wrote:
    >>>
    >>>> now suppose I have declared an integer value inside a function as
    >>>> int x; now if the return type of the function is of type (void *)
    >>>> then can
    >>>> I write return((void *)x) in side the function?
    >>>


    < snipped getting ahead of myself >

    > Vladimir, I think you misread the details in the OP's question: as far
    > as I onderstood, he is not returning the address of x, but the *value*
    > of x, casted to void * :
    >
    >>>> return((void *)x)

    >
    > Apart from the cast, this is just as valid as returning x intself.


    Ah, you're absolutely right (and so is Eric). I stand corrected.

    I think I jumped ahead of myself (and OP), thinking of what one would
    _do_ with such a value returned from the function. Trying to
    dereference it would most likely be a bad idea (unless maybe one is
    implementing a *alloc() replacement).

    Cheers

    Vladimir


    --
    Democracy is a device that insures we shall be governed no better than
    we deserve.
    -- George Bernard Shaw
     
    Vladimir S. Oka, Jan 30, 2006
    #10
  11. Ico wrote:

    > Vladimir S. Oka <> wrote:
    >> Ico wrote:
    >>
    >>> Hello AbhishV00ek,
    >>>
    >>> Abhishek <> wrote:
    >>>

    >
    > Vladimir, I think you misread the details in the OP's question: as far
    > as I onderstood, he is not returning the address of x, but the *value*
    > of x, casted to void * :
    >
    >>>> return((void *)x)

    >
    > Apart from the cast, this is just as valid as returning x intself.
    >
    > Ico
    >


    Vladimir, you muppet! You are henceforth barred from posting before 9 AM
    and/or before having at least three (3) mugs of strong coffee!

    The above applies to my previous reply, especially (which I still can't
    see, and think will have to do un/re-subscribe to c.l.c dance again)!

    Clerk, please strike Vladimir's statements in this case.

    I'm kneeling on some corns for a while... :-(

    Cheers

    Vladimir

    --
    Hark ye, Clinker, you are a most notorious offender. You stand
    convicted of sickness, hunger, wretchedness, and want.
    -- Tobias Smollet
     
    Vladimir S. Oka, Jan 30, 2006
    #11
  12. Abhishek

    Old Wolf Guest

    Eric Sosman wrote:
    > The O.P. has run across a function whose return type is
    > `void*' <ot> because of the requirements of a framework that
    > is not topical here </ot>. However, in the context of the
    > actual function it makes more sense to return an `int'. The
    > code tries to do so by converting the `int' to a `void*';
    > presumably, the caller retrieves the `void*' and converts it
    > back to an `int' again. The O.P. asks whether C guarantees
    > that this will work as desired.
    >
    > The answer (may I have the envelope, please?) is "No."
    >
    > That said, the dubious practice will in fact work as desired
    > on many implementations (I suspect it might fail on AS/400, but
    > I'm not sure of that). Completely portable approaches exist,
    > but some programmers are too lazy or too unimaginative to use
    > them. The O.P. is looking at such a programmer's product.


    A portable solution within this framework is to make x static
    and return its address. Then convert back to (int *) in the
    calling function.
     
    Old Wolf, Jan 30, 2006
    #12
  13. Abhishek

    Eric Sosman Guest

    Re: CAN WE TYPE CAST AN INTEGER AS (VOID *)X..(Like can I returna value (void *)x)

    Old Wolf wrote On 01/30/06 08:28,:
    > Eric Sosman wrote:
    >
    >> The O.P. has run across a function whose return type is
    >>`void*' <ot> because of the requirements of a framework that
    >>is not topical here </ot>. However, in the context of the
    >>actual function it makes more sense to return an `int'. The
    >>code tries to do so by converting the `int' to a `void*';
    >>presumably, the caller retrieves the `void*' and converts it
    >>back to an `int' again. The O.P. asks whether C guarantees
    >>that this will work as desired.
    >>
    >> The answer (may I have the envelope, please?) is "No."
    >>
    >> That said, the dubious practice will in fact work as desired
    >>on many implementations (I suspect it might fail on AS/400, but
    >>I'm not sure of that). Completely portable approaches exist,
    >>but some programmers are too lazy or too unimaginative to use
    >>them. The O.P. is looking at such a programmer's product.

    >
    >
    > A portable solution within this framework is to make x static
    > and return its address. Then convert back to (int *) in the
    > calling function.


    Yes, <ot> but that's not a good idea in multi-
    threaded code, which is what the O.P. is studying.
    As it happens, the POSIX multi-threading framework
    dictates that the signature of the function must be

    void* function(void*)

    .... and it's easy to use the argument as a pointer
    to a place where the "returned" value -- int, double,
    or whatever -- can be deposited. </ot>

    Another safe way to disguise a smallish integer
    as a pointer is to point at something:

    char fake[10];
    ...
    void* function(void* arg) {
    int x;
    ...
    return &fake[x]; /* 0 <= x <= 10 */
    }
    ...
    /* caller: */
    int x = (char*)result_of_f - fake;

    --
     
    Eric Sosman, Jan 30, 2006
    #13
    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. Ollej Reemt
    Replies:
    7
    Views:
    602
    Jack Klein
    Apr 22, 2005
  2. Stig Brautaset

    `void **' revisited: void *pop(void **root)

    Stig Brautaset, Oct 25, 2003, in forum: C Programming
    Replies:
    15
    Views:
    836
    The Real OS/2 Guy
    Oct 28, 2003
  3. Replies:
    5
    Views:
    881
    S.Tobias
    Jul 22, 2005
  4. Replies:
    2
    Views:
    499
    Tomás
    May 2, 2006
  5. Hakirato
    Replies:
    4
    Views:
    933
    Alf P. Steinbach
    Oct 5, 2006
Loading...

Share This Page