Discussion:
No casting of void* ???
(too old to reply)
Robby
2009-09-02 21:27:01 UTC
Permalink
Hello again!

Okay, in the previous thread (void* passed as functin parameters) I have
been taugth that:

a) If members in structs are identical, we can make a seperate typedefed
base structure containing the identical members only and access them from
there.

b) The base struct is really not necessary, but it makes the solution more
symmetric between the types.

c) I could use C++ and incorporate templates in my code so we know the type
being pass in before hand so to solve this dilema.

d) Macro functions are interesting, but there is too much to modify in my
current code. I would of had to start doing this from the begining of the
project.

e) Assigning an enum pointer as Uli suggested.

I have played with this and to my surprise I have a code sample version that
works without having done any of the above. I am not critisising anyone's
suggestions here, all your suggestions are valid and you guys did very well
for me and as always and I greatly appreciate it. I just want to dimistify
this so I understand why it works. Its weird, here's the code:

=================================
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// TABLES
typedef struct tag_pc_table
{
long z;
long h;
long j;
}pc_table;

typedef struct tag_lb_table
{
long z;
long h;
int yyy;
}lb_table;

// OBJECTS
typedef struct tag_pc {
long w;
struct tag_pc_table *dc;
} pc;

typedef struct tag_lb {
long w;
struct tag_lb_table *dc;
} lb;

void f1(void *x)
{
pc *p = x;
long t,x;

t = p->dc[0].z;
x = p->dc[0].h;

t->dc[0].z = 998;
x->dc[0].h = 999;
}

int main()
{
long t;
pc *a;
lb *b;

pc_table apc[] = {101, 102}; // Fill one record
lb_table alb[] = {201, 202}; // Fill one record

a = malloc(sizeof (struct tag_pc));
a->dc = apc;
f1(a);

b = malloc(sizeof (struct tag_lb));
b->dc = alb;
f1(b);

t = a->dc[0].z;
t = b->dc[0].h;

free(a); free(b); return 0;
}
====================================

The lines that puzzel me are the following lines in f1():

t = p->dc[0].z;
t = p->dc[0].h;

p->dc[0].z = 998;
p->dc[0].h = 999;

If we pass in the "a" variable to f1() which is a pointer of pc type and we
even further type cast it in f1() with:

pc *p = x;

then, I understand that t and x are equal to 101, 102 respectively as they
get accessed by:

t = p->dc[0].z;
t = p->dc[0].h;

But, if when we pass in the "b" variable to f1() which is a pointer of lb
type and we still cast it in f1() with:

pc *p = x;

and I am stil able to get the correct t and x values as 201, 202
respectively as they get accessed by:

t = p->dc[0].z;
t = p->dc[0].h;

is weird... to me anyways. Its because we casted the lb pointer as a pc type
and its somehow still able to go and get the correct values of 201 and 202
via the following pointer member:

struct tag_pc_table *dc;

when the correct pointer to access those values should of been:

struct tag_lb_table *dc;

which resides in the lb type struct ???? In the previous thread, we did
agree, that this was not possible and wouldn't work... no?

So the example code above simply casts in f1() like this:

pc *p = x;

and miraculously (so to speak !) I all of the sudden have access to members
in the tag_pc_table or tag_lb_table tables via the dc pointer in the
struct tag_pc structure even though whatever I passed in got casted to pc
type?

I like it, because it works and it does what I need, I don't like it because
I don't know why it works!

All feedback appreciated!
--
Best regards
Roberto
Igor Tandetnik
2009-09-02 21:56:45 UTC
Permalink
Post by Robby
I have played with this and to my surprise I have a code sample
version that works without having done any of the above. I am not
critisising anyone's suggestions here, all your suggestions are
valid and you guys did very well for me and as always and I greatly
appreciate it. I just want to dimistify this so I understand why it
Try a) making sure the two table structures are different size, as they
are in your real code, and b) accessing table elements at indexes other
than zero. Then you'll notice that your assignments go to all the wrong
places.
Post by Robby
=================================
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// TABLES
typedef struct tag_pc_table
{
long z;
long h;
long j;
}pc_table;
typedef struct tag_lb_table
{
long z;
long h;
int yyy;
}lb_table;
// OBJECTS
typedef struct tag_pc {
long w;
struct tag_pc_table *dc;
} pc;
typedef struct tag_lb {
long w;
struct tag_lb_table *dc;
} lb;
void f1(void *x)
{
pc *p = x;
long t,x;
t = p->dc[0].z;
x = p->dc[0].h;
t->dc[0].z = 998;
x->dc[0].h = 999;
This can't possibly compile - t is not a pointer. Post your actual code.
Post by Robby
But, if when we pass in the "b" variable to f1() which is a pointer
pc *p = x;
and I am stil able to get the correct t and x values as 201, 202
t = p->dc[0].z;
t = p->dc[0].h;
is weird... to me anyways.
The binary layout of the structures is compatible enough for this to
work out. Remember, the compiled code doesn't deal with names, but with
addresses and offsets and such.
Post by Robby
Its because we casted the lb pointer as a
pc type and its somehow still able to go and get the correct values
struct tag_pc_table *dc;
struct tag_lb_table *dc;
which resides in the lb type struct ???? In the previous thread, we
did agree, that this was not possible and wouldn't work... no?
That would depend on what the definition of "we" is. I personally didn't
agree with any such thing. My example in that thread relies heavily on
the ability to access members of layout-compatible structures via
pointers of a wrong type (witness the ThreeLinks structure).
--
With best wishes,
Igor Tandetnik

With sufficient thrust, pigs fly just fine. However, this is not
necessarily a good idea. It is hard to be sure where they are going to
land, and it could be dangerous sitting under them as they fly
overhead. -- RFC 1925
Robby
2009-09-03 13:52:02 UTC
Permalink
Hello Igor,
Post by Igor Tandetnik
This can't possibly compile - t is not a pointer. Post your actual code.
Careless me!, Here you go, this compiles:

===================================
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// TABLES
typedef struct tag_pc_table
{
long z;
long h;
long j;
}pc_table;

typedef struct tag_lb_table
{
long z;
long h;
}lb_table;

// OBJECTS
typedef struct tag_pc {
long w;
struct tag_pc_table *dc;
} pc;

typedef struct tag_lb {
long w;
struct tag_lb_table *dc;
} lb;

void f1(void *x)
{
pc *p = x;

long t,o;

t = p->dc[0].z;
o = p->dc[0].h;

p->dc[0].z = 998;
p->dc[0].h = 999;
}

int main()
{
long t;
pc *a;
lb *b;

pc_table apc[] = {101, 102}; // Fill one record
lb_table alb[] = {201, 202}; // Fill one record

a = malloc(sizeof (struct tag_pc));
a->dc = apc;
f1(a);

b = malloc(sizeof (struct tag_lb));
b->dc = alb;
f1(b);

t = a->dc[0].z;
t = b->dc[0].h;

free(a);
free(b);
return 0;
}
=============================
Post by Igor Tandetnik
The binary layout of the structures is compatible enough for this to
work out. Remember, the compiled code doesn't deal with names, but with
addresses and offsets and such.
I think I understand what's going on here! I am getting fooled by thinking
that I am referencing the lb_table members when in reality I am always using
the pc_table ones since they are the same (atleast for the members I am
referencing) .

But now, given this issue, like many have told me to use a base structure,
this changes things.... I will post again, standby!
--
Best regards
Roberto
Post by Igor Tandetnik
Post by Robby
I have played with this and to my surprise I have a code sample
version that works without having done any of the above. I am not
critisising anyone's suggestions here, all your suggestions are
valid and you guys did very well for me and as always and I greatly
appreciate it. I just want to dimistify this so I understand why it
Try a) making sure the two table structures are different size, as they
are in your real code, and b) accessing table elements at indexes other
than zero. Then you'll notice that your assignments go to all the wrong
places.
Post by Robby
=================================
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// TABLES
typedef struct tag_pc_table
{
long z;
long h;
long j;
}pc_table;
typedef struct tag_lb_table
{
long z;
long h;
int yyy;
}lb_table;
// OBJECTS
typedef struct tag_pc {
long w;
struct tag_pc_table *dc;
} pc;
typedef struct tag_lb {
long w;
struct tag_lb_table *dc;
} lb;
void f1(void *x)
{
pc *p = x;
long t,x;
t = p->dc[0].z;
x = p->dc[0].h;
t->dc[0].z = 998;
x->dc[0].h = 999;
This can't possibly compile - t is not a pointer. Post your actual code.
Post by Robby
But, if when we pass in the "b" variable to f1() which is a pointer
pc *p = x;
and I am stil able to get the correct t and x values as 201, 202
t = p->dc[0].z;
t = p->dc[0].h;
is weird... to me anyways.
The binary layout of the structures is compatible enough for this to
work out. Remember, the compiled code doesn't deal with names, but with
addresses and offsets and such.
Post by Robby
Its because we casted the lb pointer as a
pc type and its somehow still able to go and get the correct values
struct tag_pc_table *dc;
struct tag_lb_table *dc;
which resides in the lb type struct ???? In the previous thread, we
did agree, that this was not possible and wouldn't work... no?
That would depend on what the definition of "we" is. I personally didn't
agree with any such thing. My example in that thread relies heavily on
the ability to access members of layout-compatible structures via
pointers of a wrong type (witness the ThreeLinks structure).
--
With best wishes,
Igor Tandetnik
With sufficient thrust, pigs fly just fine. However, this is not
necessarily a good idea. It is hard to be sure where they are going to
land, and it could be dangerous sitting under them as they fly
overhead. -- RFC 1925
Robby
2009-09-03 16:33:01 UTC
Permalink
Hello,

Okay, I seem to have accomplished a solution that compiles and satisfies the
usage of a single function to replace other identical ones. I pretty much
used alot of the feedback you guys gave me in the previous post.

There's one thing though, you see, the whole objective of my tables at the
top of any of my windProc functions is so the programmer can fill out the
informations he desires for every record. For example if I do this:

============================================
void wndProc1()
{
// declare a pc pointer
pc *a;

// Fill 2 records
pc_table apc[] = {
0, 0, 100, 10,
1, 0, 150, 11};

============================================

means that the first two fields for every record in the apc array depict the
identification links that correspond to the rest of the record. So for
example, if another window procedure sends two global variables identifying
the linking fields as 1 and 0, then this wndProc will compare these fields to
a matching record in the apc array! That's basically what the
lb_match_link_id() function I showed Igor does... well actually it would also
return the record's location in the array and then beased on the record's
location I would use the rest of the data in this record for other
functionality to the control.

Having said, this, to create base structures so to condense identical
structure elements into one structure causes me to loose out on the
compactability of the table configuartion shown above. Basically, now, the
table would have to be fragmented in two structures. I am not saying that
base structures are no good, all I am saying is that it was nice to just have
the linking ID fields embeded in its associated record right then and there.
And perhaps, I am wrong in thinking in this methodological way. I just seemed
to find it convenient.

Is it that I shoud get used to seperating data at the expense of creating
more structures and leaving behind the fact that now instead of filling out
one table, I would have to fill two of them.... (as shown in sample below)
then if so, then okay, I will have to change my habits.

Here is what I have come up with... mostly done with base structures!

============================================
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// BASE TABLE
typedef struct tag_table_links
{
long LK__F1;
long LK__F2;
}table_links;

// TABLES
typedef struct tag_pc_table
{
long j;
int y;
}pc_table;

typedef struct tag_lb_table
{
long r;
char s[10];
}lb_table;


// BASE OBJECT
typedef struct tag_obj_links {
struct tag_table_links *dc;
} obj_links;

typedef struct tag_pc {
int i;
} pc;

typedef struct tag_lb {
char s[10];
} lb;

// common code Function!
void f1(obj_links *o, table_links *x)
{
if(o->dc->LK__F1 == x->LK__F1)
{
// then do something....
}
}


void wndProc1()
{
// declare a pc pointer
pc *a;

// Declare an object_links object to hold incoming links
obj_links *ol = NULL;

// Data links desired from previous control
// (1,0) targets the second apc record!
long Link_Id1_from_Previous_WndProc = 1;
long Link_Id2_from_Previous_WndProc = 0;

// Programmer configures respective links that coresponding
// to the 2 apc records in the pc_table
table_links atl[] = {
0, 0,
1, 0};

// Fill 2 records
pc_table apc[] = {
100, 10,
150, 11};

// Assign the links to a base struct
ol->dc->LK__F1 = Link_Id1_from_Previous_WndProc;
ol->dc->LK__F2 = Link_Id2_from_Previous_WndProc;

// create object
a = (pc*) malloc(sizeof (struct tag_pc));
// Fill out the object's data members

a->i = 10;
// Now! I can use a common function to do stuff
f1(ol, atl);

free(a);
}

void wndProc2()
{
// declare an lb pointer
lb *b;

// Declare an object_links object to hold incoming links
obj_links *ol = NULL;

// Data links desired from previous control
long Link_Id1_from_Another_WndProc = 5;
long Link_Id2_from_Another_WndProc = 2;

// Programmer configures respective links that coresponding
// to the 5 alb records in the lb_table
table_links atl[] = {
{0, 0},
{1, 0},
{1, 1},
{5, 2},
{5, 3},};

// Fill 5 records
lb_table alb[] = {
500, "structs",
188, "pointers",
468, "code",
89, "prog",
333, "list",};

// Assign the links to a base struct
ol->dc->LK__F1 = Link_Id1_from_Another_WndProc;
ol->dc->LK__F2 = Link_Id2_from_Another_WndProc;

// create object
b = (lb*) malloc(sizeof (struct tag_lb));

// Fill out the object's data members
strcpy_s(b->s, "abc");

// Now! I can use a common function to do stuff
f1(ol, atl);

free(b);
}


int main()
{
wndProc1();
wndProc2();
return 0;
}
========================================

Okay, soryy for the long sample code, but it was necessary to show how the
f1() function works out.

Link_Id1_from_Previous_WndProc and Link_Id2_from_Previous_WndProc variables
are really global variables that would be set by some other WndProc, I just
put them local here just for the sample's purpose.

Is the above code acceptable as an object configuration technique?

All feedback regrading my posts is well appreciated guys!
--
Best regards
Roberto
Post by Robby
Hello Igor,
Post by Igor Tandetnik
This can't possibly compile - t is not a pointer. Post your actual code.
===================================
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// TABLES
typedef struct tag_pc_table
{
long z;
long h;
long j;
}pc_table;
typedef struct tag_lb_table
{
long z;
long h;
}lb_table;
// OBJECTS
typedef struct tag_pc {
long w;
struct tag_pc_table *dc;
} pc;
typedef struct tag_lb {
long w;
struct tag_lb_table *dc;
} lb;
void f1(void *x)
{
pc *p = x;
long t,o;
t = p->dc[0].z;
o = p->dc[0].h;
p->dc[0].z = 998;
p->dc[0].h = 999;
}
int main()
{
long t;
pc *a;
lb *b;
pc_table apc[] = {101, 102}; // Fill one record
lb_table alb[] = {201, 202}; // Fill one record
a = malloc(sizeof (struct tag_pc));
a->dc = apc;
f1(a);
b = malloc(sizeof (struct tag_lb));
b->dc = alb;
f1(b);
t = a->dc[0].z;
t = b->dc[0].h;
free(a);
free(b);
return 0;
}
=============================
Post by Igor Tandetnik
The binary layout of the structures is compatible enough for this to
work out. Remember, the compiled code doesn't deal with names, but with
addresses and offsets and such.
I think I understand what's going on here! I am getting fooled by thinking
that I am referencing the lb_table members when in reality I am always using
the pc_table ones since they are the same (atleast for the members I am
referencing) .
But now, given this issue, like many have told me to use a base structure,
this changes things.... I will post again, standby!
--
Best regards
Roberto
Post by Igor Tandetnik
Post by Robby
I have played with this and to my surprise I have a code sample
version that works without having done any of the above. I am not
critisising anyone's suggestions here, all your suggestions are
valid and you guys did very well for me and as always and I greatly
appreciate it. I just want to dimistify this so I understand why it
Try a) making sure the two table structures are different size, as they
are in your real code, and b) accessing table elements at indexes other
than zero. Then you'll notice that your assignments go to all the wrong
places.
Post by Robby
=================================
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// TABLES
typedef struct tag_pc_table
{
long z;
long h;
long j;
}pc_table;
typedef struct tag_lb_table
{
long z;
long h;
int yyy;
}lb_table;
// OBJECTS
typedef struct tag_pc {
long w;
struct tag_pc_table *dc;
} pc;
typedef struct tag_lb {
long w;
struct tag_lb_table *dc;
} lb;
void f1(void *x)
{
pc *p = x;
long t,x;
t = p->dc[0].z;
x = p->dc[0].h;
t->dc[0].z = 998;
x->dc[0].h = 999;
This can't possibly compile - t is not a pointer. Post your actual code.
Post by Robby
But, if when we pass in the "b" variable to f1() which is a pointer
pc *p = x;
and I am stil able to get the correct t and x values as 201, 202
t = p->dc[0].z;
t = p->dc[0].h;
is weird... to me anyways.
The binary layout of the structures is compatible enough for this to
work out. Remember, the compiled code doesn't deal with names, but with
addresses and offsets and such.
Post by Robby
Its because we casted the lb pointer as a
pc type and its somehow still able to go and get the correct values
struct tag_pc_table *dc;
struct tag_lb_table *dc;
which resides in the lb type struct ???? In the previous thread, we
did agree, that this was not possible and wouldn't work... no?
That would depend on what the definition of "we" is. I personally didn't
agree with any such thing. My example in that thread relies heavily on
the ability to access members of layout-compatible structures via
pointers of a wrong type (witness the ThreeLinks structure).
--
With best wishes,
Igor Tandetnik
With sufficient thrust, pigs fly just fine. However, this is not
necessarily a good idea. It is hard to be sure where they are going to
land, and it could be dangerous sitting under them as they fly
overhead. -- RFC 1925
Continue reading on narkive:
Loading...