how to cast from (void*) to other types?

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Roman Mashak

    how to cast from (void*) to other types?

    Hello, All!

    I'm implementing function parsing config file, which look like this:

    # this is comment
    port=10000
    path=/var/run/dump.pid
    ....

    Declared the type

    #define BUFLEN 1024
    typedef struct config_s {
    char parameter[BUFLEN];
    void *value;
    } config_t;
    ....
    #define N 10 /* number of parameters in config file */
    config_t conf[N];
    ....
    strcpy(conf[0].parameter, "debug");
    conf[0].value = value;
    ....

    It's supposed to keep parameter name and it's value, which can be different
    type (string or unsigned int), that's why I use 'void*' pointer. But at this
    point I faced with the problem of type casting. If I call, for example:

    strcpy(conf[5].parameter, "port");
    conf[PORT].value = (unsigned short)value;

    than get compiler's warning:

    config.c:61: warning: cast from pointer to integer of different size
    config.c:61: warning: assignment makes pointer from integer without a cast

    I'd wish to keep values of different types in my structure. How is better
    and correct to fulfil this?

    With best regards, Roman Mashak. E-mail: mrv@tusur.ru


  • Ravi Uday

    #2
    Re: how to cast from (void*) to other types?



    Roman Mashak wrote:[color=blue]
    > Hello, All!
    >
    > I'm implementing function parsing config file, which look like this:
    >
    > # this is comment
    > port=10000
    > path=/var/run/dump.pid
    > ...
    >
    > Declared the type
    >
    > #define BUFLEN 1024
    > typedef struct config_s {
    > char parameter[BUFLEN];
    > void *value;
    > } config_t;
    > ...
    > #define N 10 /* number of parameters in config file */
    > config_t conf[N];
    > ...
    > strcpy(conf[0].parameter, "debug");
    > conf[0].value = value;
    > ...
    >
    > It's supposed to keep parameter name and it's value, which can be different
    > type (string or unsigned int), that's why I use 'void*' pointer. But at this
    > point I faced with the problem of type casting. If I call, for example:
    >
    > strcpy(conf[5].parameter, "port");
    > conf[PORT].value = (unsigned short)value;
    >
    > than get compiler's warning:
    >
    > config.c:61: warning: cast from pointer to integer of different size
    > config.c:61: warning: assignment makes pointer from integer without a cast
    >[/color]

    AFAIK, casting any pointer type to (void *) need not be typecasted.
    Its automatically casted for you based on the input you provide.

    In your case i feel 'value' is NOT a pointer type, hence its cribbing.
    Whats the data type of variable 'value' ?

    Can you post a minimal code snippet which best describes the problem.


    - Ravi

    [color=blue]
    > I'd wish to keep values of different types in my structure. How is better
    > and correct to fulfil this?
    >
    > With best regards, Roman Mashak. E-mail: mrv@tusur.ru
    >
    >[/color]

    Comment

    • Bjørn Augestad

      #3
      Re: how to cast from (void*) to other types?

      Roman Mashak wrote:[color=blue]
      > Hello, All!
      >
      > I'm implementing function parsing config file, which look like this:
      >
      > # this is comment
      > port=10000
      > path=/var/run/dump.pid
      > ...
      >
      > Declared the type
      >
      > #define BUFLEN 1024
      > typedef struct config_s {
      > char parameter[BUFLEN];
      > void *value;
      > } config_t;[/color]

      Consider storing the value as a char* or char array instead of a void*.
      Makes life much easier. Just convert the value to the appropriate type
      when you want to use it, e.g.
      int myval = config_get_int( "port");
      const char* path = config_get_stri ng("path");

      Bjørn
      [snip]

      Comment

      • Richard Heathfield

        #4
        Re: how to cast from (void*) to other types?

        Roman Mashak said:
        [color=blue]
        > #define BUFLEN 1024
        > typedef struct config_s {
        > char parameter[BUFLEN];
        > void *value;
        > } config_t;
        > ...
        > #define N 10 /* number of parameters in config file */
        > config_t conf[N];
        > ...
        > strcpy(conf[0].parameter, "debug");
        > conf[0].value = value;
        > ...
        >
        > It's supposed to keep parameter name and it's value, which can be
        > different type (string or unsigned int), that's why I use 'void*' pointer.[/color]

        Simpler: store a string representation of your int, and just strtol it back
        to an int when you need to. Much, much simpler than what you are trying to
        do, and commensurately more likely to work.
        [color=blue]
        > But at this point I faced with the problem of type casting. If I call, for
        > example:
        >
        > strcpy(conf[5].parameter, "port");
        > conf[PORT].value = (unsigned short)value;
        >
        > than get compiler's warning:
        >
        > config.c:61: warning: cast from pointer to integer of different size
        > config.c:61: warning: assignment makes pointer from integer without a cast[/color]

        Right. I can't see any good reason for the (unsigned short) cast. It doesn't
        help you in any way. Nor, in fact, would any cast at all. You could do
        this:

        conf[PORT].value = &value;

        and that would compile just fine, but it wouldn't solve your problem;
        instead, it would litter your program with pointers to an object that is
        almost certainly local in scope - a very bad idea (and no, making it global
        isn't the answer either; two wrongs don't make a right).
        [color=blue]
        > I'd wish to keep values of different types in my structure. How is better
        > and correct to fulfil this?[/color]

        If you want to get it working, keep it simple.

        #define BUFLEN 1024
        #define MAXLEN whatever you think is right
        typedef struct config_s {
        char parameter[BUFLEN];
        int valuetype; /* 0 = str, 1 = unsigned int, 2 = double, 3=?... */
        char strvalue[MAXLEN];
        unsigned int uivalue;
        double dvalue;
        } config_t;

        --
        Richard Heathfield
        "Usenet is a strange place" - dmr 29/7/1999

        email: rjh at above domain (but drop the www, obviously)

        Comment

        • Roman Mashak

          #5
          Re: how to cast from (void*) to other types?

          Hello, Richard!
          You wrote on Mon, 19 Dec 2005 07:09:21 +0000 (UTC):

          [skip]
          RH> unsigned int uivalue;
          RH> double dvalue;
          RH> } config_t;
          Thanks to everyone for help!

          With best regards, Roman Mashak. E-mail: mrv@tusur.ru


          Comment

          • David Resnick

            #6
            Re: how to cast from (void*) to other types?

            [color=blue]
            >Richard Heathfield wrote:
            > If you want to get it working, keep it simple.
            >
            > #define BUFLEN 1024
            > #define MAXLEN whatever you think is right
            > typedef struct config_s {
            > char parameter[BUFLEN];
            > int valuetype; /* 0 = str, 1 = unsigned int, 2 = double, 3=?... */
            > char strvalue[MAXLEN];
            > unsigned int uivalue;
            > double dvalue;
            > } config_t;
            >[/color]

            Once doing this, why not put the values in a union? This is the
            one of the canonical places for one...

            -David

            Comment

            • Richard Heathfield

              #7
              Re: how to cast from (void*) to other types?

              David Resnick said:
              [color=blue]
              > Once doing this, why not put the values in a union? This is the
              > one of the canonical places for one...[/color]

              It depends on his needs, of course. It can be useful to be able to associate
              more than one value type with a given name.

              --
              Richard Heathfield
              "Usenet is a strange place" - dmr 29/7/1999

              email: rjh at above domain (but drop the www, obviously)

              Comment

              • David Resnick

                #8
                Re: how to cast from (void*) to other types?


                Richard Heathfield wrote:[color=blue]
                > David Resnick said:
                >[color=green]
                > > Once doing this, why not put the values in a union? This is the
                > > one of the canonical places for one...[/color]
                >
                > It depends on his needs, of course. It can be useful to be able to associate
                > more than one value type with a given name.
                >[/color]

                Yeah, but OP said

                "It's supposed to keep parameter name and it's value, which can be
                different
                type (string or unsigned int)"

                While it might be useful to keep multiple types, he didn't ask for it.
                Mind you, I prefer your other suggestion, keep everything as strings
                then use accessors (config_get_str ing, config_get_doub le,
                config_get_int,
                config_get_bool , etc) to decied what to convert the string to. Neater.

                -David

                Comment

                • Roman Mashak

                  #9
                  Re: how to cast from (void*) to other types?

                  Hello, David!
                  You wrote on 19 Dec 2005 06:49:20 -0800:

                  DR> "It's supposed to keep parameter name and it's value, which can be
                  DR> different
                  DR> type (string or unsigned int)"

                  DR> While it might be useful to keep multiple types, he didn't ask for it.
                  DR> Mind you, I prefer your other suggestion, keep everything as strings
                  DR> then use accessors (config_get_str ing, config_get_doub le,
                  DR> config_get_int,
                  DR> config_get_bool , etc) to decied what to convert the string to. Neater.
                  The method proposed by RH earlier works fine for me. What about using
                  unions, can you give example to let me understand clearly?

                  With best regards, Roman Mashak. E-mail: mrv@tusur.ru


                  Comment

                  • David Resnick

                    #10
                    Re: how to cast from (void*) to other types?


                    Roman Mashak wrote:[color=blue]
                    > Hello, David!
                    > You wrote on 19 Dec 2005 06:49:20 -0800:
                    >
                    > DR> "It's supposed to keep parameter name and it's value, which can be
                    > DR> different
                    > DR> type (string or unsigned int)"
                    >
                    > DR> While it might be useful to keep multiple types, he didn't ask for it.
                    > DR> Mind you, I prefer your other suggestion, keep everything as strings
                    > DR> then use accessors (config_get_str ing, config_get_doub le,
                    > DR> config_get_int,
                    > DR> config_get_bool , etc) to decied what to convert the string to. Neater.
                    > The method proposed by RH earlier works fine for me. What about using
                    > unions, can you give example to let me understand clearly?
                    >
                    > With best regards, Roman Mashak. E-mail: mrv@tusur.ru[/color]

                    Instead of doing this:

                    typedef struct config_s {
                    char parameter[BUFLEN];
                    int valuetype; /* 0 = str, 1 = unsigned int, 2 = double, 3=?... */
                    char strvalue[MAXLEN];
                    unsigned int uivalue;
                    double dvalue;

                    } config_t;

                    You could do this:

                    typedef struct config_s {
                    char parameter[BUFLEN];
                    int valuetype; /* 0 = str, 1 = unsigned int, 2 = double, 3=?... */
                    union {
                    char strvalue[MAXLEN];
                    unsigned int uivalue;
                    double dvalue;
                    } value;
                    } config_t;

                    Having it be a union has a few virtues

                    1) saves memory, which usually isn't a big deal, but could be if you
                    have a union of lots of types

                    2) clarifies intent. These values are mutually exclusive. You should
                    have
                    exactly one of them.

                    That said, I think it makes rather more sense to have a config
                    mechanism
                    where everything is strings and the accessor determines what the type
                    is...

                    -David

                    Comment

                    • Chad

                      #11
                      Re: how to cast from (void*) to other types?

                      Roman Mashak wrote:[color=blue]
                      > Hello, All!
                      >
                      > I'm implementing function parsing config file, which look like this:
                      >
                      > # this is comment
                      > port=10000
                      > path=/var/run/dump.pid
                      > ...
                      >
                      > Declared the type
                      >
                      > #define BUFLEN 1024
                      > typedef struct config_s {
                      > char parameter[BUFLEN];
                      > void *value;
                      > } config_t;
                      > ...
                      > #define N 10 /* number of parameters in config file */
                      > config_t conf[N];
                      > ...
                      > strcpy(conf[0].parameter, "debug");
                      > conf[0].value = value;
                      > ...
                      >
                      > It's supposed to keep parameter name and it's value, which can be different
                      > type (string or unsigned int), that's why I use 'void*' pointer. But at this
                      > point I faced with the problem of type casting. If I call, for example:
                      >
                      > strcpy(conf[5].parameter, "port");
                      > conf[PORT].value = (unsigned short)value;
                      >
                      > than get compiler's warning:
                      >
                      > config.c:61: warning: cast from pointer to integer of different size
                      > config.c:61: warning: assignment makes pointer from integer without a cast
                      >
                      > I'd wish to keep values of different types in my structure. How is better
                      > and correct to fulfil this?
                      >
                      > With best regards, Roman Mashak. E-mail: mrv@tusur.ru[/color]

                      Maybe I need to re-read this thread again. But when I go like:

                      #include <stdio.h>
                      #include <string.h>

                      #define BUFLEN 1024
                      #define N 10

                      typedef struct config_s {
                      char parameter[BUFLEN];
                      void *value;

                      } config_t;

                      int main(void) {
                      config_t conf[N];


                      strcpy(conf[0].parameter, "debug");
                      conf[0].value = value;

                      strcpy(conf[5].parameter, "port");

                      return 0;
                      }

                      $gcc -Wall structs.c -o structs
                      structs.c: In function `main':
                      structs.c:18: error: `value' undeclared (first use in this function)
                      structs.c:18: error: (Each undeclared identifier is reported only once
                      structs.c:18: error: for each function it appears in.)
                      $

                      when I add the line 'int value;' in main() and compile with full
                      warnings using gcc, I get no warnings.

                      Chad

                      Comment

                      • Flash Gordon

                        #12
                        Re: how to cast from (void*) to other types?

                        Chad wrote:

                        <snip>
                        [color=blue]
                        > Maybe I need to re-read this thread again. But when I go like:
                        >
                        > #include <stdio.h>
                        > #include <string.h>
                        >
                        > #define BUFLEN 1024
                        > #define N 10
                        >
                        > typedef struct config_s {
                        > char parameter[BUFLEN];
                        > void *value;
                        >
                        > } config_t;
                        >
                        > int main(void) {
                        > config_t conf[N];[/color]

                        Adding the line:
                        int value=0;
                        [color=blue]
                        > strcpy(conf[0].parameter, "debug");
                        > conf[0].value = value;
                        >
                        > strcpy(conf[5].parameter, "port");
                        >
                        > return 0;
                        > }
                        >
                        > $gcc -Wall structs.c -o structs
                        > structs.c: In function `main':
                        > structs.c:18: error: `value' undeclared (first use in this function)
                        > structs.c:18: error: (Each undeclared identifier is reported only once
                        > structs.c:18: error: for each function it appears in.)
                        > $
                        >
                        > when I add the line 'int value;' in main() and compile with full
                        > warnings using gcc, I get no warnings.[/color]

                        You should get a warning along the lines of:
                        structs.c:19: warning: assignment makes pointer from integer without a cast
                        If not you are either not doing what you say or you are using a broken
                        version of gcc (which I don't believe).

                        <OT>
                        You could try adding the -ansi -pedantic switches since these are
                        required to make gcc comply with C89, you can get it to come close to
                        C99 with different options, but it never fully complies with C99.
                        </OT>

                        The reason I know that all working version of gcc produce a warning or
                        error for the code you've described is that integer types, such as int,
                        are not assignment compatible with pointers of any type, so for a
                        compiler to conform to the standard it is *required* to produce a
                        diagnostic and the code is *not* required to work even if you add in a
                        cast to shut the compiler up.
                        --
                        Flash Gordon
                        Living in interesting times.
                        Although my email address says spam, it is real and I read it.

                        Comment

                        Working...