By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
446,260 Members | 1,409 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 446,260 IT Pros & Developers. It's quick & easy.

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

P: n/a
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: mr*@tusur.ru
Dec 19 '05 #1
Share this Question
Share on Google+
11 Replies


P: n/a


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: mr*@tusur.ru


Dec 19 '05 #2

P: n/a
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]
Dec 19 '05 #3

P: n/a
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)
Dec 19 '05 #4

P: n/a
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: mr*@tusur.ru
Dec 19 '05 #5

P: n/a
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

Dec 19 '05 #6

P: n/a
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)
Dec 19 '05 #7

P: n/a

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

Dec 19 '05 #8

P: n/a
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: mr*@tusur.ru
Dec 20 '05 #9

P: n/a

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: mr*@tusur.ru


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

Dec 20 '05 #10

P: n/a
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: mr*@tusur.ru


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

Dec 21 '05 #11

P: n/a
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.
Dec 21 '05 #12

This discussion thread is closed

Replies have been disabled for this discussion.