By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
454,497 Members | 2,373 Online
Bytes IT Community
+ Ask a Question
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 <stdio.h>
// 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
Share this Question
Share on Google+
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 <stdio.h>
// 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 <stdio.h>
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" <gedum...@bellsouth.netwrote:
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 <stdio.h>
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 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 <stdio.h>
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 <stdio.h>
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]: <http://cbfalconer.home.att.net>
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 <es*****@ieee-dot-org.invalidwrites:
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.
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 <http://www.ghoti.net/~kst>
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" <ge******@bellsouth.netwrote in message
news:FN*******************@bignews9.bellsouth.net. ..
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 <stdio.h>
// 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:

<http://www.catb.org/~esr/faqs/smart-questions.html>
<http://www.caliburn.nl/topposting.html>
<http://www.netmeister.org/news/learn2quote.html>
<http://cfaj.freeshell.org/google/ (taming google)
<http://members.fortunecity.com/nnqweb/ (newusers)

--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.
Nov 9 '08 #13

This discussion thread is closed

Replies have been disabled for this discussion.