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

Discussion in 'C Programming' started by Ravi Uday, Dec 19, 2005.

  1. Ravi Uday

    Ravi Uday Guest

    Roman Mashak wrote:
    > 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
    >


    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


    > 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:
    >
    >
    Ravi Uday, Dec 19, 2005
    #1
    1. Advertising

  2. Roman Mashak wrote:
    > 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;


    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_string("path");

    Bjørn
    [snip]
    =?ISO-8859-1?Q?Bj=F8rn_Augestad?=, Dec 19, 2005
    #2
    1. Advertising

  3. Roman Mashak said:

    > #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.


    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.

    > 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


    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).

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


    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
    http://www.cpax.org.uk
    email: rjh at above domain (but drop the www, obviously)
    Richard Heathfield, Dec 19, 2005
    #3
  4. Ravi Uday

    Roman Mashak Guest

    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:
    Roman Mashak, Dec 19, 2005
    #4
  5. Ravi Uday

    Roman Mashak Guest

    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:
    Roman Mashak, Dec 19, 2005
    #5

  6. >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;
    >


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

    -David
    David Resnick, Dec 19, 2005
    #6
  7. David Resnick said:

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


    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
    http://www.cpax.org.uk
    email: rjh at above domain (but drop the www, obviously)
    Richard Heathfield, Dec 19, 2005
    #7
  8. Richard Heathfield wrote:
    > David Resnick said:
    >
    > > Once doing this, why not put the values in a union? This is the
    > > one of the canonical places for one...

    >
    > 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.
    >


    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_string, config_get_double,
    config_get_int,
    config_get_bool, etc) to decied what to convert the string to. Neater.

    -David
    David Resnick, Dec 19, 2005
    #8
  9. Ravi Uday

    Roman Mashak Guest

    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_string, config_get_double,
    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:
    Roman Mashak, Dec 20, 2005
    #9
  10. Roman Mashak wrote:
    > 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_string, config_get_double,
    > 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:


    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
    David Resnick, Dec 20, 2005
    #10
  11. Ravi Uday

    Chad Guest

    Roman Mashak wrote:
    > 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:


    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
    Chad, Dec 21, 2005
    #11
  12. Ravi Uday

    Flash Gordon Guest

    Chad wrote:

    <snip>

    > 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];


    Adding the line:
    int value=0;

    > 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.


    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.
    Flash Gordon, Dec 21, 2005
    #12
    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:
    502
    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:
    778
    The Real OS/2 Guy
    Oct 28, 2003
  3. Replies:
    5
    Views:
    815
    S.Tobias
    Jul 22, 2005
  4. Abhishek
    Replies:
    12
    Views:
    792
    Eric Sosman
    Jan 30, 2006
  5. Replies:
    1
    Views:
    395
    Victor Bazarov
    May 23, 2007
Loading...

Share This Page