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

R

Ravi Uday

Roman said:
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
 
?

=?ISO-8859-1?Q?Bj=F8rn_Augestad?=

Roman said:
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]
 
R

Richard Heathfield

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

Roman Mashak

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: (e-mail address removed)
 
R

Roman Mashak

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: (e-mail address removed)
 
D

David Resnick

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
 
R

Richard Heathfield

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

David Resnick

Richard said:
David Resnick said:


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
 
R

Roman Mashak

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: (e-mail address removed)
 
D

David Resnick

Roman said:
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: (e-mail address removed)

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
 
C

Chad

Roman said:
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: (e-mail address removed)

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
 
F

Flash Gordon

Chad wrote:

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.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top