Is this valid C statement?

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • s.subbarayan

    #1

    Is this valid C statement?

    Dear all,
    According to standards is this valid:

    char TmpPtrWriteBuff er[1000];
    void* PtrWriteBuffer =(void*) TmpPtrWriteBuff er;

    I had a debate with my colleagues that anything cant be typecasted to
    void* though the reverse is true.But they said this is valid.
    I just can't agree with them with out a valid explaination.Ca n any C
    standard experts clarify me this?

    Regards,
    s.subbarayan
  • Joona I Palaste

    #2
    Re: Is this valid C statement?

    s.subbarayan <s_subbarayan@r ediffmail.com> scribbled the following:[color=blue]
    > Dear all,
    > According to standards is this valid:[/color]
    [color=blue]
    > char TmpPtrWriteBuff er[1000];
    > void* PtrWriteBuffer =(void*) TmpPtrWriteBuff er;[/color]
    [color=blue]
    > I had a debate with my colleagues that anything cant be typecasted to
    > void* though the reverse is true.But they said this is valid.
    > I just can't agree with them with out a valid explaination.Ca n any C
    > standard experts clarify me this?[/color]

    You are right on this one. A pointer to anything can be assigned into a
    void *, even without a cast. However, this does not mean that any void *
    can always safely be assigned into any other pointer type. There might
    be alignment conflicts or other, possibly implementation-dependent,
    issues.
    For example the following code will usually not work:

    char *cp;
    int *ip;
    void *vp;
    if (cp=malloc(1000 )) {
    vp = cp+1;
    ip = vp;
    }

    Even though the code compiles nicely, it might cause errors at run-time,
    because the line ip = vp; assigns a pointer value that is not properly
    aligned to int into a int pointer. (This is assuming sizeof(int)>1.)

    --
    /-- Joona Palaste (palaste@cc.hel sinki.fi) ------------- Finland --------\
    \-- http://www.helsinki.fi/~palaste --------------------- rules! --------/
    "To err is human. To really louse things up takes a computer."
    - Anon

    Comment

    • xarax

      #3
      Re: Is this valid C statement?

      "s.subbaray an" <s_subbarayan@r ediffmail.com> wrote in message
      news:c396173e.0 409270206.167ad 4c3@posting.goo gle.com...[color=blue]
      > Dear all,
      > According to standards is this valid:
      >
      > char TmpPtrWriteBuff er[1000];
      > void* PtrWriteBuffer =(void*) TmpPtrWriteBuff er;
      >
      > I had a debate with my colleagues that anything cant be typecasted to
      > void* though the reverse is true.But they said this is valid.
      > I just can't agree with them with out a valid explaination.Ca n any C
      > standard experts clarify me this?[/color]

      Your colleagues are correct. A pointer of type (void*)
      has the same alignment requirements and internal representation
      as a (char*). The symbol "TmpPtrWriteBuf fer" deteriorates
      to type (char*), so casting it to (void*) doesn't harm
      the integrity of the pointer value. The target symbol
      "PtrWriteBuffer " has type (void*), so the assignment
      from (void*) to (void*) is also valid.


      Comment

      • Joona I Palaste

        #4
        Re: Is this valid C statement?

        Joona I Palaste <palaste@cc.hel sinki.fi> scribbled the following:[color=blue]
        > s.subbarayan <s_subbarayan@r ediffmail.com> scribbled the following:[color=green]
        >> Dear all,
        >> According to standards is this valid:[/color][/color]
        [color=blue][color=green]
        >> char TmpPtrWriteBuff er[1000];
        >> void* PtrWriteBuffer =(void*) TmpPtrWriteBuff er;[/color][/color]
        [color=blue][color=green]
        >> I had a debate with my colleagues that anything cant be typecasted to
        >> void* though the reverse is true.But they said this is valid.
        >> I just can't agree with them with out a valid explaination.Ca n any C
        >> standard experts clarify me this?[/color][/color]
        [color=blue]
        > You are right on this one. A pointer to anything can be assigned into a
        > void *, even without a cast. However, this does not mean that any void *
        > can always safely be assigned into any other pointer type. There might
        > be alignment conflicts or other, possibly implementation-dependent,
        > issues.
        > For example the following code will usually not work:[/color]
        [color=blue]
        > char *cp;
        > int *ip;
        > void *vp;
        > if (cp=malloc(1000 )) {
        > vp = cp+1;
        > ip = vp;
        > }[/color]
        [color=blue]
        > Even though the code compiles nicely, it might cause errors at run-time,
        > because the line ip = vp; assigns a pointer value that is not properly
        > aligned to int into a int pointer. (This is assuming sizeof(int)>1.)[/color]

        Sorry, after having read xarax's reply, I have found out that I have
        answered the wrong question. Yes, your colleagues are correct in that
        a pointer to anything can be assigned to void * with or without a cast.
        As I have shown above, the assignment back in the other direction will
        not necessarily work.

        --
        /-- Joona Palaste (palaste@cc.hel sinki.fi) ------------- Finland --------\
        \-- http://www.helsinki.fi/~palaste --------------------- rules! --------/
        "When a man talks dirty to a woman, that's sexual harassment. When a woman talks
        dirty to a man, that's 14.99 per minute + local telephone charges!"
        - Ruben Stiller

        Comment

        • S.Tobias

          #5
          Re: Is this valid C statement?

          Joona I Palaste <palaste@cc.hel sinki.fi> wrote:
          [color=blue]
          > answered the wrong question. Yes, your colleagues are correct in that
          > a pointer to anything can be assigned to void * with or without a cast.[/color]

          ....provided that "anything" is not a function.

          --
          Stan Tobias
          sed 's/[A-Z]//g' to email

          Comment

          • Dan Pop

            #6
            Re: Is this valid C statement?

            In <cj8pl7$6vd$1@o ravannahka.hels inki.fi> Joona I Palaste <palaste@cc.hel sinki.fi> writes:
            [color=blue]
            >s.subbarayan <s_subbarayan@r ediffmail.com> scribbled the following:[color=green]
            >> Dear all,
            >> According to standards is this valid:[/color]
            >[color=green]
            >> char TmpPtrWriteBuff er[1000];
            >> void* PtrWriteBuffer =(void*) TmpPtrWriteBuff er;[/color]
            >[color=green]
            >> I had a debate with my colleagues that anything cant be typecasted to
            >> void* though the reverse is true.But they said this is valid.
            >> I just can't agree with them with out a valid explaination.Ca n any C
            >> standard experts clarify me this?[/color]
            >
            >You are right on this one. A pointer to anything can be assigned into a
            >void *, even without a cast. ^^^^^^^^[/color]

            You are wrong on this one. Pointers to functions cannot be converted
            (either explicitly or implicitly) to pointers to void (and vice versa).
            Undefined behaviour due to lack of specification in the standard.

            Dan
            --
            Dan Pop
            DESY Zeuthen, RZ group
            Email: Dan.Pop@ifh.de
            Currently looking for a job in the European Union

            Comment

            • Joona I Palaste

              #7
              Re: Is this valid C statement?

              Dan Pop <Dan.Pop@cern.c h> scribbled the following:[color=blue]
              > In <cj8pl7$6vd$1@o ravannahka.hels inki.fi> Joona I Palaste <palaste@cc.hel sinki.fi> writes:[color=green]
              >>s.subbaraya n <s_subbarayan@r ediffmail.com> scribbled the following:[color=darkred]
              >>> Dear all,
              >>> According to standards is this valid:[/color]
              >>[color=darkred]
              >>> char TmpPtrWriteBuff er[1000];
              >>> void* PtrWriteBuffer =(void*) TmpPtrWriteBuff er;[/color]
              >>[color=darkred]
              >>> I had a debate with my colleagues that anything cant be typecasted to
              >>> void* though the reverse is true.But they said this is valid.
              >>> I just can't agree with them with out a valid explaination.Ca n any C
              >>> standard experts clarify me this?[/color]
              >>
              >>You are right on this one. A pointer to anything can be assigned into a
              >>void *, even without a cast. ^^^^^^^^[/color][/color]
              [color=blue]
              > You are wrong on this one. Pointers to functions cannot be converted
              > (either explicitly or implicitly) to pointers to void (and vice versa).
              > Undefined behaviour due to lack of specification in the standard.[/color]

              Yes, I should have realised that. Read "anything" as "any object type"
              and it will work. Thanks for the correction, Dan.

              --
              /-- Joona Palaste (palaste@cc.hel sinki.fi) ------------- Finland --------\
              \-- http://www.helsinki.fi/~palaste --------------------- rules! --------/
              "A bee could, in effect, gather its junk. Llamas (no poor quadripeds) tune
              and vow excitedly zooming."
              - JIPsoft

              Comment

              • pete

                #8
                Re: Is this valid C statement?

                Joona I Palaste wrote:[color=blue]
                >
                > Dan Pop <Dan.Pop@cern.c h> scribbled the following:[/color]
                [color=blue][color=green]
                > > Pointers to functions cannot be converted
                > > (either explicitly or implicitly) to pointers to void
                > > (and vice versa).
                > > Undefined behaviour due to lack of specification in the standard.[/color]
                >
                > Yes, I should have realised that. Read "anything" as "any object type"
                > and it will work. Thanks for the correction, Dan.[/color]

                "anything" could read to include incomplete types too.

                --
                pete

                Comment

                • kal

                  #9
                  Re: Is this valid C statement?

                  Joona I Palaste <palaste@cc.hel sinki.fi> wrote in message news:<cj983i$ec 6$1@oravannahka .helsinki.fi>.. .
                  [color=blue]
                  > Sorry, after having read xarax's reply, I have found out that I have
                  > answered the wrong question. Yes, your colleagues are correct in that
                  > a pointer to anything can be assigned to void * with or without a cast.
                  > As I have shown above, the assignment back in the other direction will
                  > not necessarily work.[/color]

                  int *ptr_to_int = malloc(100 * sizeof *ptr_to_int);

                  Comment

                  • Joona I Palaste

                    #10
                    Re: Is this valid C statement?

                    kal <k_amir7@yahoo. com> scribbled the following:[color=blue]
                    > Joona I Palaste <palaste@cc.hel sinki.fi> wrote in message news:<cj983i$ec 6$1@oravannahka .helsinki.fi>.. .[color=green]
                    >> Sorry, after having read xarax's reply, I have found out that I have
                    >> answered the wrong question. Yes, your colleagues are correct in that
                    >> a pointer to anything can be assigned to void * with or without a cast.
                    >> As I have shown above, the assignment back in the other direction will
                    >> not necessarily work.[/color][/color]
                    [color=blue]
                    > int *ptr_to_int = malloc(100 * sizeof *ptr_to_int);[/color]

                    What's that supposed to mean? I said "will not necessarily work", not
                    "will never work".

                    --
                    /-- Joona Palaste (palaste@cc.hel sinki.fi) ------------- Finland --------\
                    \-- http://www.helsinki.fi/~palaste --------------------- rules! --------/

                    Comment

                    • kal

                      #11
                      Re: Is this valid C statement?

                      Joona I Palaste <palaste@cc.hel sinki.fi> wrote in message news:<cjb9cd$t4 7$1@oravannahka .helsinki.fi>.. .[color=blue]
                      > kal <k_amir7@yahoo. com> scribbled the following:[color=green]
                      > > Joona I Palaste <palaste@cc.hel sinki.fi> wrote in message news:<cj983i$ec 6$1@oravannahka .helsinki.fi>.. .[color=darkred]
                      > >> Sorry, after having read xarax's reply, I have found out that I have
                      > >> answered the wrong question. Yes, your colleagues are correct in that
                      > >> a pointer to anything can be assigned to void * with or without a cast.
                      > >> As I have shown above, the assignment back in the other direction will
                      > >> not necessarily work.[/color][/color]
                      >[color=green]
                      > > int *ptr_to_int = malloc(100 * sizeof *ptr_to_int);[/color]
                      >
                      > What's that supposed to mean? I said "will not necessarily work", not
                      > "will never work".[/color]

                      1. A pointer to void can be converted to and from a pointer to
                      any object type (a function is not an object.)

                      Whether the converted pointer will be properly aligned for
                      it to be useful is another question entirely.

                      2. A pointer to any object type can be converted to a pointer
                      to character. The resulting character pointer is always
                      correctly aligned (see 6.3.2.3 (7).)

                      Since the OP's question involved conversion between "void *" and
                      "char *", it SHOULD ALWAYS work.


                      Now, from ISO/IEC 9899
                      ----------------------

                      6.3.2.3 Pointers

                      1 A pointer to void may be converted to or from a pointer to
                      any incomplete or object type. A pointer to any incomplete
                      or object type may be converted to a pointer to void and
                      back again; the result shall compare equal to the original
                      pointer.

                      7 A pointer to an object or incomplete type may be converted
                      to a pointer to a different object or incomplete type. If
                      the resulting pointer is not correctly aligned for the
                      pointed-to type, the behavior is undefined. Otherwise, when
                      converted back again, the result shall compare equal to the
                      original pointer. When a pointer to an object is converted
                      to a pointer to a character type, the result points to the
                      lowest addressed byte of the object. Successive increments
                      of the result, up to the size of the object, yield pointers
                      to the remaining bytes of the object.

                      8 A pointer to a function of one type may be converted to a
                      pointer to a function of another type and back again; the
                      result shall compare equal to the original pointer. If a
                      converted pointer is used to call a function whose type is
                      not compatible with the pointed-to type, the behavior is
                      undefined.


                      [The reason I used "malloc" is because of the following. The
                      emphasis here is on the phrase "suitably aligned."]

                      7.20.3 Memory management functions

                      1 ...
                      The pointer returned if the allocation succeeds is
                      suitably aligned so that it may be assigned to a
                      pointer to any type of object and then used to access
                      such an object or an array of such objects in the space
                      allocated
                      ...

                      Comment

                      • John Harrison

                        #12
                        Re: Is this valid C statement?


                        "Dan Pop" <Dan.Pop@cern.c h> wrote in message
                        news:cj99sp$qvh $8@sunnews.cern .ch...[color=blue][color=green]
                        >>You are right on this one. A pointer to anything can be assigned into a
                        >>void *, even without a cast. ^^^^^^^^[/color]
                        >
                        > You are wrong on this one. Pointers to functions cannot be converted
                        > (either explicitly or implicitly) to pointers to void (and vice versa).
                        > Undefined behaviour due to lack of specification in the standard.
                        >[/color]

                        I can't comment as to what is/isn't in the standard, however the following
                        compiles and runs (without any warnings) on every system I have:

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

                        typedef int (*fooptr)(int);

                        int foo(int bar) {
                        printf("foo(%d) \n", bar);
                        return bar;
                        }

                        int main(void) {
                        fooptr f1 = NULL;
                        fooptr f2 = NULL;
                        void* v1 = NULL;

                        f1 = foo;

                        /* cast function pointer to void* */
                        v1 = (void*)f1;

                        /* cast void* to function pointer */
                        f2 = (fooptr)v1;

                        f1(1);
                        f2(2);
                        return 0;
                        }


                        In fact, the dlopen()/dlsym() dynamic loading system used on most Unix
                        systems wouldn't work if you couldn't convert a void* to a function
                        pointer...




                        Comment

                        • CBFalconer

                          #13
                          Re: Is this valid C statement?

                          John Harrison wrote:[color=blue]
                          > "Dan Pop" <Dan.Pop@cern.c h> wrote in message
                          >[/color]
                          .... snip ...[color=blue][color=green]
                          >>
                          >> You are wrong on this one. Pointers to functions cannot be
                          >> converted (either explicitly or implicitly) to pointers to
                          >> void (and vice versa). Undefined behaviour due to lack of
                          >> specification in the standard.[/color]
                          >
                          > I can't comment as to what is/isn't in the standard, however the
                          > following compiles and runs (without any warnings) on every
                          > system I have:
                          >
                          > #include <stdio.h>
                          > #include <stdlib.h>
                          >
                          > typedef int (*fooptr)(int);
                          >
                          > int foo(int bar) {
                          > printf("foo(%d) \n", bar);
                          > return bar;
                          > }
                          >
                          > int main(void) {
                          > fooptr f1 = NULL;
                          > fooptr f2 = NULL;
                          > void* v1 = NULL;
                          >
                          > f1 = foo;
                          > /* cast function pointer to void* */
                          > v1 = (void*)f1;
                          > /* cast void* to function pointer */
                          > f2 = (fooptr)v1;
                          >
                          > f1(1);
                          > f2(2);
                          > return 0;
                          > }
                          >
                          > In fact, the dlopen()/dlsym() dynamic loading system used on most
                          > Unix systems wouldn't work if you couldn't convert a void* to a
                          > function pointer...[/color]

                          Which doesn't affect the fact that the conversions are not
                          guaranteed. Any such Unix functions are obviously system
                          specific, and don't need portability. A pointer to a function can
                          easily require more bits than are present in a void*.

                          BTW the casts are unnecessary and bad practice.

                          --
                          A: Because it fouls the order in which people normally read text.
                          Q: Why is top-posting such a bad thing?
                          A: Top-posting.
                          Q: What is the most annoying thing on usenet and in e-mail?


                          Comment

                          • Dan Pop

                            #14
                            Re: Is this valid C statement?

                            In <415bf574$1@haw k.winshop.com.a u> "John Harrison" <john@hiame.com > writes:

                            [color=blue]
                            >"Dan Pop" <Dan.Pop@cern.c h> wrote in message
                            >news:cj99sp$qv h$8@sunnews.cer n.ch...[color=green][color=darkred]
                            >>>You are right on this one. A pointer to anything can be assigned into a
                            >>>void *, even without a cast. ^^^^^^^^[/color]
                            >>
                            >> You are wrong on this one. Pointers to functions cannot be converted
                            >> (either explicitly or implicitly) to pointers to void (and vice versa).
                            >> Undefined behaviour due to lack of specification in the standard.
                            >>[/color]
                            >
                            >I can't comment as to what is/isn't in the standard, however the following
                            >compiles and runs (without any warnings) on every system I have:[/color]

                            So what? Invoking undefined behaviour doesn't require any warning.
                            [color=blue]
                            >#include <stdio.h>
                            >#include <stdlib.h>
                            >
                            >typedef int (*fooptr)(int);
                            >
                            >int foo(int bar) {
                            > printf("foo(%d) \n", bar);
                            > return bar;
                            >}
                            >
                            >int main(void) {
                            > fooptr f1 = NULL;
                            > fooptr f2 = NULL;
                            > void* v1 = NULL;
                            >
                            > f1 = foo;
                            >
                            > /* cast function pointer to void* */
                            > v1 = (void*)f1;
                            >
                            > /* cast void* to function pointer */
                            > f2 = (fooptr)v1;
                            >
                            > f1(1);
                            > f2(2);
                            > return 0;
                            >}
                            >
                            >
                            >In fact, the dlopen()/dlsym() dynamic loading system used on most Unix
                            >systems wouldn't work if you couldn't convert a void* to a function
                            >pointer...[/color]

                            So what? This is comp.lang.c, not comp.unix.progr ammer. The fact that
                            the C standard does not define the conversion between void pointers and
                            function pointers doesn't mean that a Unix-specific standard cannot
                            define it.

                            Your program may not work on MS-DOS under certain memory models (16-bit
                            data pointers and 32-bit function pointers) and on AS/400 machines
                            (function pointers much wider than data pointers).

                            The standard provides no guarantee that void pointers are wide enough
                            to be able to store function pointers. In the absence of this guarantee,
                            your code doesn't qualify as portable.

                            Dan
                            --
                            Dan Pop
                            DESY Zeuthen, RZ group
                            Email: Dan.Pop@ifh.de
                            Currently looking for a job in the European Union

                            Comment

                            • Dan Pop

                              #15
                              Re: Is this valid C statement?

                              In <415C10BC.489F7 0C4@yahoo.com> CBFalconer <cbfalconer@yah oo.com> writes:
                              [color=blue]
                              >John Harrison wrote:[color=green]
                              >>
                              >> #include <stdio.h>
                              >> #include <stdlib.h>
                              >>
                              >> typedef int (*fooptr)(int);
                              >>
                              >> int foo(int bar) {
                              >> printf("foo(%d) \n", bar);
                              >> return bar;
                              >> }
                              >>
                              >> int main(void) {
                              >> fooptr f1 = NULL;
                              >> fooptr f2 = NULL;
                              >> void* v1 = NULL;
                              >>
                              >> f1 = foo;
                              >> /* cast function pointer to void* */
                              >> v1 = (void*)f1;
                              >> /* cast void* to function pointer */
                              >> f2 = (fooptr)v1;
                              >>
                              >> f1(1);
                              >> f2(2);
                              >> return 0;
                              >> }
                              >>[/color]
                              >BTW the casts are unnecessary and bad practice.[/color]

                              You forgot to engage the brain, again!

                              Without the casts, the program violates the constraints of 6.5.16.1p1 and
                              requires a diagnostic. With the casts, the program invokes undefined
                              behaviour and no diagnostic is required. If I remove the casts,
                              gcc complains (when invoked in conforming mode):

                              fangorn:~/tmp 284> gcc -ansi -pedantic test.c
                              test.c: In function `main':
                              test.c:19: warning: ISO C forbids assignment between function pointer and `void *'
                              test.c:22: warning: ISO C forbids assignment between function pointer and `void *'

                              With the casts in place, I get a clean compile from gcc, which is OK.

                              Dan
                              --
                              Dan Pop
                              DESY Zeuthen, RZ group
                              Email: Dan.Pop@ifh.de
                              Currently looking for a job in the European Union

                              Comment

                              Working...