Different Pointer Types
Steve Watt
steve at wattres.UUCP
Thu Mar 8 15:45:54 AEST 1990
In article <31530004 at hpcvia.CV.HP.COM> brianh at hpcvia.CV.HP.COM (brian_helterline) writes:
+I have a question about the following code. Given a structure like:
+
+struct FOO {
+ int type_of_data;
+ int number_of_elements;
+ union {
+ int *int_ptr;
+ unsigned int *un_int_ptr;
+ long *long_ptr;
+ } ptr;
+ };
+
+And a fuction to sum up the elements:
+
+double sum( struct FOO foo )
+{
[somewhat long broken code omitted, see original article]
+}
+Here are my questions:
+
+1) Is the above code ok? (other that typos which I've missed.)
No. When a pointer to char is dereferenced, you get a char. ONLY.
The summing routine needs to be somewhat uglier... Either the switch
statement needs to be inside the summing loop, or create a function that
returns double, given a pointer to the data type, and create an array of
them.
typedef enum {
int_data, unsigned_data, long_data
} data_type;
struct FOO {
data_type type_of_data;
int number_of_elements;
int size_of_element; /* In case you want to get some other weird type */
/* Set to sizeof(data_type) */
union {
/* These are not really needed for this set of routines...
int *int_ptr;
unsigned int *un_int_ptr;
long *long_ptr;
*/
void *void_ptr;
} ptr;
};
double iptod(void *), uptod(void *), lptod(void *);
double (*funcs[])(void *) = {
iptod, uptod, lptod
};
double sum( struct FOO foo ) { /* Cogito ergo sum? :) */
int i;
void *p = foo.ptr.void_ptr;
double tmp = 0.0;
for (i = 0; i < foo.number_of_elements; i++) {
tmp += funcs[foo.type_of_data](p); /* see note below */
p = (char *)p + foo.size_of_element;
}
/* Non-ANSI compilers would require the noted line to be something like:
tmp += (*funcs[foo.type_of_data])(p);
Some people may also prefer this.
*/
return (tmp);
}
double iptod( void *p ) {
return (double) (*(int *)p) ;
}
double uptod( void *p ) {
return (double) (*(unsigned *)p) ;
}
double lptod( void *p ) {
return (double) (*(long *)p) ;
}
Notice that this code is easy to extend to a new data type: If you need
to support snorkelwackers, then change the enum to be:
int_data, unsigned_data, long_data, snorkelwacker_data
add this prototype:
double snorkelwackerptod(void *); /* In the prototypes */
add snorkelwackerptod to the function array, so it looks like
iptod, uptod, lptod, snorkelwackerptod
and
double snorkelwackerptod( void *p ) {
return (double) (*((snorkelwacker *)p)->snkwck_data_1);
}
Tah dah! You can now sum up snorkelwacker data, as well!
+2) Is this the best way to handle different types of pointers? I realize
+ that the above code depends on sizof( char ) == 1. What is a
+ better way? I am stuck with the struct *AS IS*.
The best way is to use C++ :).
By the way: sizeof(char) is defined to be 1.
+Thanks for any/all help/advice
No problem!
--
Steve Watt
...!claris!wattres!steve wattres!steve at claris.com also works
If you torture your data long enough, it'll eventually confess.
More information about the Comp.lang.c
mailing list