454,497 Members | 2,373 Online
Need help? Post your question and get tips & solutions from a community of 454,497 IT Pros & Developers. It's quick & easy.

# Shared pointers???

 P: n/a Hi, in C... is there any such thing as an "any" type pointer? In the example below, is there any way that I could define function "x" to accept a pointer of type "struct a" or "struct b", or any other structure I might create with an "int i", so I wouldn't have to create multiple functions that do exactly the same thing? Let's assume I have a valid reason for having separate structures with similar data. I would just like to share function "x" and eliminate function "y". I could have many more similar structures and I'd like to use generic function "x" for all of them. Is there any way I can do that? #include // Structure "a" typedef struct { int i; } a; // Structure "b" typedef struct { int i; char s[5]; } b; // Function "x" void x(a *p) { (*p).i = 10; } // Function "y" void y(b *p) { (*p).i = 20; } int main(void) { a a1; b b1; x(&a1); y(&b1); printf("a1.i = %d, b1.i = %d\n", a1.i, b1.i); return 0; } Nov 7 '08 #1
12 Replies

 P: n/a gedumer1 wrote: Hi, in C... is there any such thing as an "any" type pointer? There's `void*', but it won't do what you want. In the example below, is there any way that I could define function "x" to accept a pointer of type "struct a" or "struct b", A function parameter has one and only one type. You may be able to call it with argument expressions of other types, but they will be converted to the parameter's type before the function sees them. That is, the function can "accept" any argument that is convertible to the type of the corresponding parameter, but what the function actually receives is a value of the parameter's type. There is no way the function can discover the type of the argument expression prior to conversion. or any other structure I might create with an "int i", so I wouldn't have to create multiple functions that do exactly the same thing? Let's assume I have a valid reason for having separate structures with similar data. I would just like to share function "x" and eliminate function "y". I could have many more similar structures and I'd like to use generic function "x" for all of them. Is there any way I can do that? [... code snipped ...] If the struct types all have a "common initial sequence" of elements (for example, if they all begin with an `int' followed by a `char*' with possibly different things following), then you can put all the struct types into a union and hand the function a pointer to the union. The function can then work with the common elements regardless of which kind of struct the union actually holds at the moment. An approach that avoids the union is to put the common elements in their own little struct, and to make that struct the first element of each of the real structs: struct common { int i; char *cp; }; struct type1 { struct common c; double d; }; struct type2 { struct common c; float fa[10]; }; You can then pass the function a pointer to the `c' element of each struct, and the function can access the elements of the `c' without worrying about what kind of super-struct contains it. -- Er*********@sun.com Nov 7 '08 #2

 P: n/a gedumer1 wrote: Hi, in C... is there any such thing as an "any" type pointer? Yes, just use void*p. However, you have to keep track of what type of object it points at, and you'll have to change it back to the original pointer type before dereferencing it: void set_to_one(void *p, enum pointer_type type) { switch(type) { case INT_TYPE: { *(int*)p = 1; } case DOUBLE_TYPE: { *(double*)p = 1.0; } // etc. } } In the example below, is there any way that I could define function "x" to accept a pointer of type "struct a" or "struct b", or any other structure I might create with an "int i", so I wouldn't have to create multiple functions that do exactly the same thing? Let's assume I have a valid reason for having separate structures with similar data. I would just like to share function "x" and eliminate function "y". I could have many more similar structures and I'd like to use generic function "x" for all of them. Is there any way I can do that? #include // Structure "a" typedef struct { int i; } a; // Structure "b" typedef struct { int i; char s[5]; } b; // Function "x" void x(a *p) { (*p).i = 10; } // Function "y" void y(b *p) { (*p).i = 20; } int main(void) { a a1; b b1; x(&a1); y(&b1); printf("a1.i = %d, b1.i = %d\n", a1.i, b1.i); return 0; } For the purposes of your code above, you don't need the complicated switch statement like I used. Your function x() only uses the first member of the structure, which is the same in all cases. There are several ways to use this fact: // Option 1: this will work for any member of any struct void x(int *p) { *p = 10;} x(&a1->i); // Option 2: this will work only for the first member of the struct void x(void*p) { *(int *)p = 10;} x(&a1); // Option 3: This will work for any element in the "common initial sequence" // of members shared between the different struct types. typedef union { a a1; b b1; } u; void x(u*p) { p->a.i = 10;} void x(u*p) { p->a.i = 20;} // Because of the "common initial sequence" rule, it doesn't matter whether those functions use // p->a.i or p->b.i; either one is equally acceptable. u u1; u u2; x(&u1); y(&u2); Nov 7 '08 #3

 P: n/a >in C... is there any such thing as an "any" type pointer? > There's `void*', but it won't do what you want. Thanks... that's the key. Look at the code below. Unless I'm not thinking straight, I think it solves the problem. struct common { int i; char *cp; }; struct type1 { struct common c; double d; }; struct type2 { struct common c; float fa[10]; }; You can then pass the function a pointer to the `c' element of each struct, and the function can access the elements of the `c' without worrying about what kind of super-struct contains it. Using a generic structure, sort of what you describe above, that will house all of the data types I want to include in the standard function should do the trick... do you agree? /****************/ #include typedef struct { int i; } generic; typedef struct { int i; } a; typedef struct { int i; char s[5]; } b; void y(void *p, int i) { generic *any; any = p; any->i = i; } int main(void) { a a1; b b1; y(&a1, 10); y(&b1, 20); printf("a1.i = %d, b1.i = %d\n", a1.i, b1.i); return 0; } /****************/ The result is: a1.i = 10, b1.i = 20 Nov 7 '08 #4

 P: n/a On Nov 7, 1:50*pm, "gedumer1" typedef struct { * int i;} generic; typedef struct { * int i;} a; typedef struct { * int i; * char s[5];} b; void y(void *p, int i) { * generic *any; * any = p; * any->i = i;} int main(void) { * a a1; * b b1; * y(&a1, 10); * y(&b1, 20); * printf("a1.i = %d, *b1.i = %d\n", a1.i, b1.i); * return 0;} /****************/ The result is: a1.i = 10, *b1.i = 20 Use a union like the Unix XEvent does: enum ( MY_TYPE_A, MY_TYPE_B, /* etc. */ } typedef struct MyTypeA { int type; /* Set to MY_TYPE_A when creating an instance */ /* Other items unique to MyTypeA*/ } MyTypeA; typedef struct MyTypeB { int type; /* Set to MY_TYPE_B when creating an instance */ /* Other items unique to MyTypeB*/ } MyTypeB; typedef union generic { int type; MyTypeA a; MyTypeB b; /* etc. */ } Generic; Then your function accepts a pointer to Generic: void foo( Generic *g ) { if ( g->type == MY_TYPE_A ) { MyTypeA *pa = (MY_TYPE_A *)g; /* do somethinng here */ } else if ( (g->type == MY_TYPE_B ) { MyTypeB *pb = (MY_TYPE_B *)g; /* do somethinng here */ } /* etc. */ } -- Fred Kleinschmidt Nov 7 '08 #5

 P: n/a gedumer1 wrote: >>in C... is there any such thing as an "any" type pointer? There's `void*', but it won't do what you want. Thanks... that's the key. Look at the code below. Unless I'm not thinking straight, I think it solves the problem. >struct common { int i; char *cp; };struct type1 { struct common c; double d; };struct type2 { struct common c; float fa[10]; };You can then pass the function a pointer to the `c' element of eachstruct, and the function can access the elements of the `c' withoutworrying about what kind of super-struct contains it. Using a generic structure, sort of what you describe above, that will house all of the data types I want to include in the standard function should do the trick... do you agree? /****************/ #include typedef struct { int i; } generic; typedef struct { int i; } a; typedef struct { int i; char s[5]; } b; void y(void *p, int i) { generic *any; any = p; any->i = i; } int main(void) { a a1; b b1; y(&a1, 10); y(&b1, 20); printf("a1.i = %d, b1.i = %d\n", a1.i, b1.i); return 0; } /****************/ The result is: a1.i = 10, b1.i = 20 Nov 7 '08 #6

 P: n/a (I hit "Send" too early on an earlier response -- sorry.) gedumer1 wrote: >>in C... is there any such thing as an "any" type pointer? There's `void*', but it won't do what you want. Thanks... that's the key. Look at the code below. Unless I'm not thinking straight, I think it solves the problem. Using a generic structure, sort of what you describe above, that will house all of the data types I want to include in the standard function should do the trick... do you agree? It is very likely to work, but I do not believe it is guaranteed 100% kosher. The Standard's language about accessing the common initial subsequence of a "family" of structures insists on all the structs being contained in a union, and there's no union here. If only the very first element matters, you can take advantage of a different rule: A pointer to a struct can be converted to a pointer to its first element, and vice versa. So if you know that the first element is always an `int', you're all set: The compiler silently converts your `struct anything*' to a `void*' at the point of the call, and inside the function you can convert that to an `int*' and use it to access the struct's initial `int' element. But this trick doesn't help you get at later elements. /****************/ #include typedef struct { int i; } generic; typedef struct { int i; } a; typedef struct { int i; char s[5]; } b; void y(void *p, int i) One drawback of `void*' as a function argument is that *any* kind of data pointer is convertible to it. The compiler will not prevent you from accidentally passing a pointer to a `double' to this function; you'll just need to be vigilant. { generic *any; any = p; any->i = i; } [...] -- Er*********@sun.com Nov 7 '08 #7

 P: n/a Eric Sosman wrote: gedumer1 wrote: >in C... is there any such thing as an "any" type pointer? There's `void*', but it won't do what you want. Yes it will, as he described it. Structures with identical initial definitions are identical over that area. Thus he can use a void*, and convert it in the function. I.e. (after his struct definitions): void *foo(void *vp) { struct x* xp = vp; xp->i = 10; return xp; } and the automatic conversion to/from void* will do what he wants. -- [mail]: Chuck F (cbfalconer at maineline dot net) [page]: Try the download section. Nov 8 '08 #8

 P: n/a CBFalconer wrote: Eric Sosman wrote: >gedumer1 wrote: >>in C... is there any such thing as an "any" type pointer? There's `void*', but it won't do what you want. Yes it will, as he described it. Structures with identical initial definitions are identical over that area. [...] .... if in a union, as I said later in the same message. If the said structs do not inhabit a union, all bets are off. If you disagree, please cite chapter and verse. -- Eric Sosman es*****@ieee-dot-org.invalid Nov 8 '08 #9

 P: n/a Eric Sosman Eric Sosman wrote: >>gedumer1 wrote:in C... is there any such thing as an "any" type pointer?There's `void*', but it won't do what you want. Yes it will, as he described it. Structures with identical initialdefinitions are identical over that area. [...] ... if in a union, as I said later in the same message. If the said structs do not inhabit a union, all bets are off. If you disagree, please cite chapter and verse. You're right, there is no chapter and verse that contradicts your statement. However, the simplest way for a compiler to satisfy the standard's requirement that the common initial subsequence must match for two structs that are members of the same union, is to satisfy that requirement for *all* structs with common initial subsequences. I would be astonished if any compiler determined a struct member's layout differently depending on whether that struct happens to be used in a union with another struct. I would support changing the standard to reflect this. -- Keith Thompson (The_Other_Keith) ks***@mib.org Nokia "We must do something. This is something. Therefore, we must do this." -- Antony Jay and Jonathan Lynn, "Yes Minister" Nov 8 '08 #10

 P: n/a Keith Thompson wrote: [... about access to "common initial sequences" ...] However, the simplest way for a compiler to satisfy the standard's requirement that the common initial subsequence must match for two structs that are members of the same union, is to satisfy that requirement for *all* structs with common initial subsequences. I would be astonished if any compiler determined a struct member's layout differently depending on whether that struct happens to be used in a union with another struct. I would support changing the standard to reflect this. Wasn't this covered in another recent thread? Similar layout is necessary but *not* sufficient! If you point at the same memory with a `struct foo*' and with a `struct bar*' (and if neither struct type contains the other as an element), the compiler may assume that changes stored through one pointer do not affect values fetched through the other. Or, to get away from structs and get back to simple types, in void func(long *foo, int *bar) { long x = *foo; *bar += 42; if (x == *foo) ... .... the compiler is allowed to omit the test because `foo' and `bar' cannot point at the same object in a correct program. Similarly with structs: Dissimilar pointers point to dissimilar and hence disjoint objects. -- Eric Sosman es*****@ieee-dot-org.invalid Nov 8 '08 #11

 P: n/a Thanks to all for your help. Because of the difficulties with this plan, I've decided to go in another, more practical, direction. "gedumer1" // Structure "a" typedef struct { int i; } a; // Structure "b" typedef struct { int i; char s[5]; } b; // Function "x" void x(a *p) { (*p).i = 10; } // Function "y" void y(b *p) { (*p).i = 20; } int main(void) { a a1; b b1; x(&a1); y(&b1); printf("a1.i = %d, b1.i = %d\n", a1.i, b1.i); return 0; } Nov 8 '08 #12

 P: n/a gedumer1 wrote: > Thanks to all for your help. Because of the difficulties with this plan, I've decided to go in another, more practical, direction. Too late - the thread has morphed into a discussion of struct ptrs. Please do not top-post. Your answer belongs after (or intermixed with) the quoted material to which you reply, after snipping all irrelevant material. See the following links: Try the download section. Nov 9 '08 #13

### This discussion thread is closed

Replies have been disabled for this discussion.