Click to See Complete Forum and Search --> : Accept a struct or a char *
debiandude
12-06-2001, 12:04 AM
I was wondering if I would be able to accomplish this. I have a c program and I would like for one of the functions to be able to accept either a struct * or a char *. What I was thing would be to declare is as a void * and then in the function test it to see if it was a char * or a struct *. But Im not sure how I would go about testing what it is, or even if that would be a valid approach.
lazy_cod3R
12-06-2001, 09:16 AM
Im not sure either how to get the type of a variable in C, but maybe you can have a second parameter saying what it is ?
0 for a struct* ?
1 for a char* ?
#define STRUCT 0
#define CHAR 1
func(void* data, int type) {
if(type == CHAR){
//process char*
}else{
//process struct*
}
}
int main(int argc,char** argv){
DataVal="Hello_world";
func((char*)DataVal,CHAR);
return 0;
}
[ 06 December 2001: Message edited by: lazy_cod3R ]
TheLinuxDuck
12-06-2001, 09:55 AM
dd:
I think l_c is right, I don't know of any way to test to see if a pointer is of a particular type. It seems logical that there would be a way, but I dunno it.
bwkaz
12-06-2001, 10:29 AM
There is in C++ -- RTTI is qool. I think it goes along the lines of __typeid(<variable> ), but I could be wrong.
If I'm right, you could test for it like this:
if(__typeid(data) == __typeid(char *)) {
// process char *
}
else {
// process struct *
}
It might also be __typeof, or, now that I think about it more, those might have just been Borland C++ extensions. Hmmm......
Stuka
12-06-2001, 10:46 AM
I gotta go with the Duck and l_c here too - unless you pass an extra parameter, the only other way to do it would be to put a known byte value at a specific point in the structure (and beware compiler packing issues!), dereference the void pointer, and check for that specific value - note that to pull this off, the value must be impossible in a C string, or your test might fail. Basically, pass the parameter, or write to functions along the lines of abs and fabs (similar function, different parameters, similar names).
debiandude
12-06-2001, 05:18 PM
Thanks, I believe I got the idea. This is what I did.
/* String is my typedef'd struct type */
void s_test(void *test)
{
String *check = (String *)test;
if(check->test == 1000) puts("Struct");
else puts("Char *");
}
As soon as I initalize a Sting in my code I set its test value to 1000. Now Stuka mention that if I do this I have to be sure that it can't be in my char *, so I figured that having a number outside the range of a char would qualify. Am I right? This seems to work... ;-)
[ 06 December 2001: Message edited by: debiandude ]
Stuka
12-07-2001, 12:44 PM
debiandude -
The only other caution I have is to make sure your test variable inside your struct is at the beginning of the struct, just so you don't have a problem if you pass a short char* to the function and start referencing random memory past the end of your variables.
jemfinch
12-07-2001, 03:46 PM
Originally posted by TheLinuxDuck:
I don't know of any way to test to see if a pointer is of a particular type. It seems logical that there would be a way, but I dunno it.
It's actually very logical that there isn't a way -- C is a statically typed language, and one of the things statically typed languages don't do is keep track of the type of variables at runtime. They check the type of variables at compiletime so they don't have to keep track of them at runtime.
The proper way to do this is to use a tagged union. Here's some pseudo-C-code (my syntax is probably horrible because I don't write C all that often at all.)
struct point = {
int x;
int y;
};
typedef enum { String, Point } tag;
struct point_or_string = {
tag t;
union {
char *str;
struct point *pt;
};
}
And then you'll write to functions to decide what to do with the point_or_string struct based on what the tag is.
That's the proper way to do sum types in C.
Jeremy
Stuka
12-07-2001, 05:14 PM
Just one more reason to love OO programming, polymorphism, overloaded functions, and RTTI! :D
debiandude
12-07-2001, 10:06 PM
jemfinch you lost me with you last post. I understand now why this what I am trying to do isn't as assummed as I though it would be. However my problem from you last post is that you say:
typedef struct _string String;
struct _string {
int test;
int len;
char *str;
};
String *s_new(const char *src)
{
String *str;
if ((str = malloc(sizeof(String))) == NULL) {
perror("MEMORY ERROR:");
}
str->len = strlen(src);
str->str = (char *) malloc(str->len + 1);
s_ccat(str->str, src);
str->test = 1000;
return str;
}
String *s_cat(String * dest, void *src)
{
String *test = (String *) src;
if (s_test(test)) {
realloc((char *) dest->str, (dest->len + test->len + 1));
s_ccat(dest->str, test->str);
} else {
src = (char *) src;
realloc((char *) dest->str, (dest->len + strlen(src) + 1));
s_ccat(dest->str, src);
}
return dest;
}
char *s_ccat(char *dest, const char *src)
{
char *tmp = dest;
while (*dest)
dest++;
while ((*dest++ = *src++) != '\0');
return tmp;
}
int s_test(void *src)
{
String *test = (String *) src;
if (test->test == 1000)
return 1;
else
return 0;
}
And with those function I would have a main like:
int main(int argc, char **argv)
{
String *str;
String *str2;
char *test = "TEst";
str = s_new("Test1");
str2 = s_new("Test2");
s_print("TEST %s %S\n", test, str);
s_cat(str, str2); /* Here and here it */
s_cat(str, test); /* It will be tested */
s_free(str);
s_free(str2);
return 0;
}
[ 07 December 2001: Message edited by: debiandude ]
[ 07 December 2001: Message edited by: debiandude ]