void * pointer convert problem.

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Eric J.Hu

    void * pointer convert problem.

    Hi,

    I have following code, want do pointer convert. It always complain:

    vcnvt.c: In function `main':
    vcnvt.c:20: warning: dereferencing `void *' pointer
    vcnvt.c:20: request for member `key' in something not a structure or union
    ---------------------------
    #include <stdio.h>
    #include <stdlib.h>

    typedef struct
    {
    u_long key;
    u_long transCmdAdd;
    u_long transCmdMod;
    u_long transCmdSub;
    u_long transCount;
    } counting_bin_t, *counting_bin_p ;

    int main()
    {
    void * vbPtr;
    counting_bin_t cBin[9];
    cBin[0].key = 9;

    vbPtr = cBin;
    printf("key is %d\n", vbPtr->key);
    }



    Thanks,
    Eric


  • Christopher Benson-Manica

    #2
    Re: void * pointer convert problem.

    Eric J.Hu <ehu@lucent.com > wrote:
    [color=blue]
    > vcnvt.c: In function `main':
    > vcnvt.c:20: warning: dereferencing `void *' pointer[/color]

    Pretty self-explanatory. You can't derefence void pointers. You can,
    however, cast them back to their real type and then dereference them.
    [color=blue]
    > int main()
    > {
    > void * vbPtr;
    > counting_bin_t cBin[9];
    > cBin[0].key = 9;[/color]
    [color=blue]
    > vbPtr = cBin;
    > printf("key is %d\n", vbPtr->key);[/color]

    /* Like so */

    printf( "key is %d\n", ((counting_bin_ t*)vbPtr)->key );
    [color=blue]
    > }[/color]

    --
    Christopher Benson-Manica | I *should* know what I'm talking about - if I
    ataru(at)cybers pace.org | don't, I need to know. Flames welcome.

    Comment

    • nelu

      #3
      Re: void * pointer convert problem.


      Eric J.Hu wrote:[color=blue]
      > Hi,
      >
      > I have following code, want do pointer convert. It always complain:
      >
      > vcnvt.c: In function `main':
      > vcnvt.c:20: warning: dereferencing `void *' pointer
      > vcnvt.c:20: request for member `key' in something not a structure or union
      > ---------------------------
      > #include <stdio.h>
      > #include <stdlib.h>
      >
      > typedef struct
      > {
      > u_long key;
      > u_long transCmdAdd;
      > u_long transCmdMod;
      > u_long transCmdSub;
      > u_long transCount;
      > } counting_bin_t, *counting_bin_p ;
      >
      > int main()[/color]

      use int main(void)
      [color=blue]
      > {
      > void * vbPtr;
      > counting_bin_t cBin[9];
      > cBin[0].key = 9;
      >
      > vbPtr = cBin;[/color]
      you tell vbPtr to point to cBin
      [color=blue]
      > printf("key is %d\n", vbPtr->key);[/color]
      vbPtr is a void pointer so it has no idea who key is. The fact that you
      do: vbPtr=cBin doesn't change the type of vbPtr from void * to
      counting_bin_t *. You could cast (counting_bin_t *)vbPtr to obtain what
      you need. Even with the cast you should be aware that
      (counting_bin_t *)vbPtr->key may not be the same as
      ((counting_bin_ t*)vbPtr)->key.

      Comment

      • Flash Gordon

        #4
        Re: void * pointer convert problem.

        Eric J.Hu wrote:[color=blue]
        > Hi,
        >
        > I have following code, want do pointer convert. It always complain:[/color]

        English may not be your first language, but that is too poor for me to
        know what you actualy want to do.
        [color=blue]
        > vcnvt.c: In function `main':
        > vcnvt.c:20: warning: dereferencing `void *' pointer[/color]

        That's simple. You are not allowed to use the * operator on a void*
        pointer. The reason being, void* is a generic pointer type so how is the
        compiler meant to know what sort of value you expect to get? Does it
        point to an int, a char or what?

        Note that:
        x->y means the same as (*x).y
        I.e., it means dereference x and then access field y within it.
        [color=blue]
        > vcnvt.c:20: request for member `key' in something not a structure or union[/color]

        That's simple as well, dereferencing a void* pointer does not give you
        something with a struture type (since it is invalid), so obviously
        trying to access a field named key within it is not possible.
        [color=blue]
        > ---------------------------
        > #include <stdio.h>
        > #include <stdlib.h>[/color]

        Your example does not use anything from stdlib.h so why include it?
        [color=blue]
        > typedef struct
        > {
        > u_long key;
        > u_long transCmdAdd;
        > u_long transCmdMod;
        > u_long transCmdSub;
        > u_long transCount;
        > } counting_bin_t, *counting_bin_p ;[/color]

        Many people think it is better not to hide either pointers or structs
        behind typedefs.
        [color=blue]
        > int main()[/color]

        If you are not using parameters, it is better to be explicit as a matter
        of habit.

        int main(void)
        [color=blue]
        > {
        > void * vbPtr;
        > counting_bin_t cBin[9];
        > cBin[0].key = 9;
        >
        > vbPtr = cBin;[/color]

        This is perfectly valid, but in your example it is pointless so I can't
        really see what you want to know about.
        [color=blue]
        > printf("key is %d\n", vbPtr->key);[/color]

        The above line is the one with the problem, since you are trying to
        dereference a void* pointer (which is illegal) and then access a field
        within the resultant value (which is again obviously impossible).

        The whole point of void* pointers is they can point to anything.

        Main returns an int, wouldn't it be better to actually do this? (C99
        allows falling of the end of main to act as if 0 was returned, but most
        compilers are not C99 compilers).

        return 0;
        [color=blue]
        > }[/color]
        --
        Flash Gordon
        Living in interesting times.
        Although my email address says spam, it is real and I read it.

        Comment

        • Eric J.Hu

          #5
          Re: void * pointer convert problem.

          Christopher,

          Thansk for your quick answer.
          If need do casting back, that's not what I want. Following is my program. I
          just want to ignore which structure it refer to. Please see line 342.

          314 u_long hbHash( upm_histogram_b in_p hPtr, u_long key,
          histogram_bin_t ype_tag hbt)
          315 {
          316 u_long i;
          317 void* bPtr;
          323 if( hbt == PROC_TIMING_BIN )
          324 {
          325 bPtr = (proc_timing_bi n_p)(&hPtr->ptBin[0]);
          326 }
          327 else if(hbt == EXEC_TIMING_BIN )
          328 {
          329 bPtr = (exec_timing_bi n_p)(&hPtr->etBin[0]);
          330 }
          340 for (i =0 ; i< MAX_HIST_BIN_SI ZE; i++)
          341 {
          342 if(key < bPtr->key)
          343 return i;
          344 else
          345 continue;
          346 bPtr ++;
          347 }
          351 return INVALID;
          352 }

          Thanks,
          Eric
          ------------------------------------------
          "Christophe r Benson-Manica" <ataru@nospam.c yberspace.org> wrote in message
          news:dp3tai$3fu $1@chessie.cirr .com...[color=blue]
          > Eric J.Hu <ehu@lucent.com > wrote:
          >[color=green]
          > > vcnvt.c: In function `main':
          > > vcnvt.c:20: warning: dereferencing `void *' pointer[/color]
          >
          > Pretty self-explanatory. You can't derefence void pointers. You can,
          > however, cast them back to their real type and then dereference them.
          >[color=green]
          > > int main()
          > > {
          > > void * vbPtr;
          > > counting_bin_t cBin[9];
          > > cBin[0].key = 9;[/color]
          >[color=green]
          > > vbPtr = cBin;
          > > printf("key is %d\n", vbPtr->key);[/color]
          >
          > /* Like so */
          >
          > printf( "key is %d\n", ((counting_bin_ t*)vbPtr)->key );
          >[color=green]
          > > }[/color]
          >
          > --
          > Christopher Benson-Manica | I *should* know what I'm talking about - if I
          > ataru(at)cybers pace.org | don't, I need to know. Flames welcome.[/color]


          Comment

          • David Resnick

            #6
            Re: void * pointer convert problem.


            Eric J.Hu wrote:[color=blue]
            > Christopher,
            >
            > Thansk for your quick answer.
            > If need do casting back, that's not what I want. Following is my program. I
            > just want to ignore which structure it refer to. Please see line 342.
            >
            > 314 u_long hbHash( upm_histogram_b in_p hPtr, u_long key,
            > histogram_bin_t ype_tag hbt)
            > 315 {
            > 316 u_long i;
            > 317 void* bPtr;
            > 323 if( hbt == PROC_TIMING_BIN )
            > 324 {
            > 325 bPtr = (proc_timing_bi n_p)(&hPtr->ptBin[0]);
            > 326 }
            > 327 else if(hbt == EXEC_TIMING_BIN )
            > 328 {
            > 329 bPtr = (exec_timing_bi n_p)(&hPtr->etBin[0]);
            > 330 }
            > 340 for (i =0 ; i< MAX_HIST_BIN_SI ZE; i++)
            > 341 {
            > 342 if(key < bPtr->key)
            > 343 return i;
            > 344 else
            > 345 continue;
            > 346 bPtr ++;
            > 347 }
            > 351 return INVALID;
            > 352 }
            >
            > Thanks,
            > Eric[/color]

            Hi Eric,

            Conversations make more sense that way.
            Folks here don't like top posting, please post after the thing being
            replied to.
            (above two lines flipped on purpose)

            Anyway, I think you aren't clear on the issue with the way
            you are trying to use void *.

            You (or at least the compiler) can't know without casting
            or assigning to something with a non-void type what object type a
            pointer to void actually refers to. You are saying on line 342 that
            bPtr, a pointer to void, is actually a pointer to some struct that has
            a
            key field. But the compiler has no way to know what type of structure
            that may be (or in particular, what the offset of the key field is
            within that
            structure).

            -David

            Comment

            • tmp123

              #7
              Re: void * pointer convert problem.

              > 317 void* bPtr;[color=blue]
              > 325 bPtr = (proc_timing_bi n_p)(&hPtr->ptBin[0]);
              > 329 bPtr = (exec_timing_bi n_p)(&hPtr->etBin[0]);
              > 342 if(key < bPtr->key)[/color]

              Hi,

              a) If the field key has the same offset in both strutures (proc and
              exec), then you can use anyone:

              if (key < (proc_timing_bi n_p *)bPtr->key ) ...

              b) If the offset is not the same, your request has no solution. The
              most near is:

              if (key < (hbt == PROC_TIMING_BIN )?(proc_timing_ bin_p
              *)bPtr->key:(exec_timi ng_bin_p *)bPtr->key ) ...

              Kind regards.

              Comment

              • Christopher Benson-Manica

                #8
                Re: void * pointer convert problem.

                Eric J.Hu <ehu@lucent.com > wrote:
                [color=blue]
                > If need do casting back, that's not what I want.[/color]

                Sadly, that's how it is. You can't dereference or increment (among
                other things) a void pointer without casting it back to what it really
                is.
                [color=blue]
                > Following is my program. I
                > just want to ignore which structure it refer to. Please see line 342.[/color]

                I see it; not only is it wrong, but so is line 346, per above. It's
                possible that you may be able to avoid the mundane solution with the
                clever use of a macro; I haven't come up with the answer so far,
                however.

                (342 and 346 preserved for context; bPtr is declared as void *)
                [color=blue]
                > 342 if(key < bPtr->key)
                > 346 bPtr ++;[/color]

                --
                Christopher Benson-Manica | I *should* know what I'm talking about - if I
                ataru(at)cybers pace.org | don't, I need to know. Flames welcome.

                Comment

                • Eric J.Hu

                  #9
                  Re: void * pointer convert problem.


                  "tmp123" <tmp123@menta.n et> wrote in message news:1135970785 .059294.45060@g 14g2000cwa.goog legroups.com...[color=blue][color=green]
                  > > 317 void* bPtr;
                  > > 325 bPtr = (proc_timing_bi n_p)(&hPtr->ptBin[0]);
                  > > 329 bPtr = (exec_timing_bi n_p)(&hPtr->etBin[0]);
                  > > 342 if(key < bPtr->key)[/color]
                  >
                  > Hi,
                  >
                  > a) If the field key has the same offset in both strutures (proc and
                  > exec), then you can use anyone:
                  >
                  > if (key < (proc_timing_bi n_p *)bPtr->key ) ...
                  >
                  > b) If the offset is not the same, your request has no solution. The
                  > most near is:
                  >
                  > if (key < (hbt == PROC_TIMING_BIN )?(proc_timing_ bin_p
                  > *)bPtr->key:(exec_timi ng_bin_p *)bPtr->key ) ...
                  >
                  > Kind regards.
                  > [/color]

                  Yeah! They have same offset, so I can choose the first solution.


                  Thanks,
                  Eric

                  Comment

                  • Christopher Benson-Manica

                    #10
                    Re: void * pointer convert problem.

                    tmp123 <tmp123@menta.n et> wrote:
                    [color=blue]
                    > a) If the field key has the same offset in both strutures (proc and
                    > exec), then you can use anyone:[/color]

                    I don't believe that's a portable assumption. The structures could
                    have different padding bits, so unless key is the first element (in
                    which case all is well, as structs can always be converted into a
                    pointer to their first element),
                    [color=blue]
                    > if (key < (proc_timing_bi n_p *)bPtr->key ) ...[/color]

                    need not work. It still doesn't fix OP's other problem, in which he
                    attempted to increment the void pointer.

                    --
                    Christopher Benson-Manica | I *should* know what I'm talking about - if I
                    ataru(at)cybers pace.org | don't, I need to know. Flames welcome.

                    Comment

                    • nelu

                      #11
                      Re: void * pointer convert problem.


                      Christopher Benson-Manica wrote:[color=blue]
                      > I don't believe that's a portable assumption. The structures could
                      > have different padding bits, so unless key is the first element (in
                      > which case all is well, as structs can always be converted into a
                      > pointer to their first element),[/color]

                      So if I have:

                      struct s1 {
                      int id;
                      char *name;
                      int year;
                      };

                      struct s2 {
                      int id;
                      char *name;
                      int year;
                      time_t tstamp;
                      };

                      ....
                      void *p;
                      struct s2 b;
                      ....
                      p=&b;
                      ((struct s1 *)p)->year=2000;
                      ....

                      the last assignment may not be portable?

                      I may be wrong, but I think GTK+ is doing something similar.

                      Comment

                      • Keith Thompson

                        #12
                        Re: void * pointer convert problem.

                        "Eric J.Hu" <ehu@lucent.com > writes:[color=blue]
                        > I have following code, want do pointer convert. It always complain:
                        >
                        > vcnvt.c: In function `main':
                        > vcnvt.c:20: warning: dereferencing `void *' pointer
                        > vcnvt.c:20: request for member `key' in something not a structure or union
                        > ---------------------------
                        > #include <stdio.h>
                        > #include <stdlib.h>
                        >
                        > typedef struct
                        > {
                        > u_long key;
                        > u_long transCmdAdd;
                        > u_long transCmdMod;
                        > u_long transCmdSub;
                        > u_long transCount;
                        > } counting_bin_t, *counting_bin_p ;[/color]
                        [snip]

                        In addition to the other comments you've gotten, what is "u_long"?
                        There is no such type declared in <stdio.h> or <stdlib.h> (or at least
                        there shouldn't be in a conforming implementation) .

                        I'm guessing that u_long is a typedef for unsigned long, but why make
                        me guess? Just use "unsigned long" directly.

                        --
                        Keith Thompson (The_Other_Keit h) kst-u@mib.org <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.

                        Comment

                        • Christopher Benson-Manica

                          #13
                          Re: void * pointer convert problem.

                          nelu <tandauioan@gma il.com> wrote:

                          (IANALL; apply salt granules as appropriate.)
                          [color=blue]
                          > struct s1 {
                          > int id;
                          > char *name;
                          > int year;
                          > };[/color]
                          [color=blue]
                          > struct s2 {
                          > int id;
                          > char *name;
                          > int year;
                          > time_t tstamp;
                          > };[/color]
                          [color=blue]
                          > ...
                          > void *p;
                          > struct s2 b;
                          > ...
                          > p=&b;
                          > ((struct s1 *)p)->year=2000;
                          > ...[/color]
                          [color=blue]
                          > the last assignment may not be portable?[/color]

                          That's my reading of 6.7.2.1 (12) of n869:

                          "Within a structure object, the non-bit-field members and the units in
                          which bit-fields reside have addresses that increase in the order in
                          which they are declared. A pointer to a structure object, suitably
                          converted, points to its initial member (or if that member is a bit-field,
                          then to the unit in which it resides), and vice versa. There may be
                          unnamed padding within a structure object, but not at its beginning."

                          There is nothing that I can see which forbids an implementation from
                          putting the year members at different offsets (due to the above
                          mentioned unnamed padding), making the code you provided nonportable.
                          Of course, non DS9K machines are unlikely to behave in such a
                          manner...
                          [color=blue]
                          > I may be wrong, but I think GTK+ is doing something similar.[/color]

                          ....which is why GTK+ can probably get away with such code.

                          --
                          Christopher Benson-Manica | I *should* know what I'm talking about - if I
                          ataru(at)cybers pace.org | don't, I need to know. Flames welcome.

                          Comment

                          • tmp123

                            #14
                            Re: void * pointer convert problem.

                            Hi,

                            The problem of jump to next item in the array can have a similar
                            analisis:

                            a) Have both structures the same size? Then, use anyone:

                            bPtr=((exec_tim ing_bin_p *)bPtr)+1;

                            b) Have structures different sizes? Two workarounds (assertion:
                            sizeof(char)==1 ):

                            b1) Save the size, and use it after:

                            if( hbt == PROC_TIMING_BIN )
                            {
                            bPtr = (proc_timing_bi n_p)(&hPtr->ptBin[0]);
                            bSize=sizeof(hP tr->ptBin[0]);
                            }
                            else if(hbt == EXEC_TIMING_BIN )
                            {
                            bPtr = (exec_timing_bi n_p)(&hPtr->etBin[0]);
                            bSize=sizeof(hP tr->etBin[0]);
                            }

                            bPtr=((char *)bPtr)+bSize;

                            b2) Do not use a local, and get the size each time:

                            bPtr=((char *)bPtr)+(hbt == PROC_TIMING_BIN )?

                            sizeof(hPtr->ptBin[0]):

                            sizeof(hPtr->etBin[0]) );

                            Kind regards.

                            Comment

                            • Christopher Benson-Manica

                              #15
                              Re: void * pointer convert problem.

                              tmp123 <tmp123@menta.n et> wrote:
                              [color=blue]
                              > b) Have structures different sizes? Two workarounds (assertion:
                              > sizeof(char)==1 ):[/color]

                              sizeof( char ) is 1, always, by definition.
                              [color=blue]
                              > b2) Do not use a local, and get the size each time:[/color]
                              [color=blue]
                              > bPtr=((char *)bPtr)+(hbt == PROC_TIMING_BIN )?[/color]
                              [color=blue]
                              > sizeof(hPtr->ptBin[0]):[/color]
                              [color=blue]
                              > sizeof(hPtr->etBin[0]) );[/color]

                              This strikes me as rather grotesque abuse of the ?= operator.

                              Additionally:

                              It is proper Usenet etiquette to include the relevant portions of the text
                              you are replying to. To do this using Google groups, please follow the
                              instructions below, penned by Keith Thompson:

                              If you want to post a followup via groups.google.c om, don't use
                              the broken "Reply" link at the bottom of the article. Click on
                              "show options" at the top of the article, then click on the
                              "Reply" at the bottom of the article headers.

                              --
                              Christopher Benson-Manica | I *should* know what I'm talking about - if I
                              ataru(at)cybers pace.org | don't, I need to know. Flames welcome.

                              Comment

                              Working...