Shared pointers???

G

gedumer1

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;
}
 
J

jameskuyper

gedumer1 said:
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);
 
G

gedumer1

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
 
F

Fred

    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. */
}
 
C

CBFalconer

Eric said:
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.
 
E

Eric Sosman

CBFalconer said:
Eric said:
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.
 
K

Keith Thompson

Eric Sosman said:
CBFalconer said:
Eric said:
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.
 
E

Eric Sosman

Keith said:
[... 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.
 
G

gedumer1

Thanks to all for your help. Because of the difficulties with this plan,
I've decided to go in another, more practical, direction.
 
C

CBFalconer

Eric said:
CBFalconer said:
Eric said:
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.

I think we can agree offhand that a pointer to the struct is also a
pointer to the first item in the structure (if suitably typed).
That is guaranteed by the standard. Also, structures are
guaranteed to assign storage in the order declared. So the only
thing that can disturb my allegation is some diddling with packing,
and I see no reason for that. I don't know of a guarantee offhand.
 
C

CBFalconer

gedumer1 said:
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)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,776
Messages
2,569,603
Members
45,196
Latest member
ScottChare

Latest Threads

Top