Single Pointer pointing to two different const str

2019-09-07 04:02发布

I have two different structures and and two const look up tables as below

typedef const struct 
{
    unsigned int  num;
    unsigned char name[100];
    unsigned int value1;
    unsigned int value2;
    unsigned int value3;
}st_Table1;

typedef const struct
{
    unsigned int  num;
    unsigned char name[100];
}st_Table2;

st_Table1 stTable1[] =
{
    { 1, "Name1", 12, 13, 14 },
    { 2, "Name2", 22, 23, 24 },
    { 3, "Name3", 32, 33, 34 },
    { 4, "Name4", 42, 43, 44 }
};



st_Table2 stTable2[] =
    { 1, "India1" },
    { 2, "India2" },
    { 3, "India3" }
};

Could it be possible to have single pointer that can point to both the lookup tables stTable1 and stTable2?

When I have to make the decision for selection of either of the two tables we can assign the address of the table (either of).

But after that I wanted to use the single pointer in the remaining code.

Please reply for any logic ... hint ... clue

Arvind

5条回答
Rolldiameter
2楼-- · 2019-09-07 04:03

You can get the same effect as the casts other have suggested with a union as well

union table_ptr {
   st_Table1*table1;
   st_Table2*table2;
} my_table_ptr;

and just assign/access the desired member.

查看更多
戒情不戒烟
3楼-- · 2019-09-07 04:06

It's impossible. A pointer must know its own range in order to read and write correctly during runtime, or you can do nothing with it. If you don't know whether it's table1 or table2, how can you write code to read it? (what type is the value in value = *pointer; ?) On the other hand, if you do know it's a table1/table2, why not use a pointer of specific type?

OR (if you insist)

Just use st_Table1 as st_Table2 and accept the waste of memory (3*sizeof(unsigned int) for each record). It won't be a big waste unless you have billions of record. You don't want to hold billions of data record by C structure.

OR (well, you hate waste)

typedef struct
{
    int num;
    char name[100];
    int *value;
}st_table;

well, you have a unified structure now. Allocate value during runtime if you need it (value = (int *)malloc(3 * sizeof(int));). Don't forget the NULL check before you read value.

查看更多
劫难
4楼-- · 2019-09-07 04:22

well you could create a struct

typedef struct _tableChoice 
{
  st_Table1* table1;
  st_Table2* table2;

} tableChoice_t,*p_tableChoice_t;

then you could pass along an argument of type p_tableChoice_t until you need to specifically access one of the tables. If you need to decide during runtime what pointer to use you would need to have both pointers available at the decision point.

查看更多
够拽才男人
5楼-- · 2019-09-07 04:22

You could create a void pointer:

void * ptr;

Like any other pointer this can point to any memory address but it doesn't specify what type of data is stored there, so you could dereference it but you'd have to depend on your own knowledge of the structures to access different elements etc.. If you have some other flag indicating what type of record it's pointing to, you could cast it back to the required type of pointer.

Given that both of your structs have common ground you'd be better off just using the first one and accepting the small overhead on memory for instances where you only need num and name. I hate software bloat and wasted memory, but you're talking about an extra 12 bytes (on most platforms) for records where value1-3 are not needed, so unless we're talking about billions of records chances are the extra code required to deal with more will consume more memory than the wasted space.

Another option could be a union, where you lose 12 bytes from name for records of the second type so that all records take up the same amount of space, though of course compiler padding my make a difference on some platforms.

查看更多
淡お忘
6楼-- · 2019-09-07 04:24

You may want to follow a similar pattern to the sockaddr family of structures. In that setup, all of the structures must have the same size and the same initial layout, something like:

typedef const struct
{
    unsigned int  num;
    unsigned char name[100];
    char buffer_[sizeof(unsigned int) * 3];
} st_TableBase;

typedef const struct 
{
    unsigned int  num;
    unsigned char name[100];
    unsigned int value1;
    unsigned int value2;
    unsigned int value3;
} st_Table1;

typedef const struct
{
    unsigned int  num;
    unsigned char name[100];
    char buffer_[sizeof(unsigned int) * 3];
} st_Table2;

With this structure, you would normally maintain a pointer of type st_TableBase. With this pointer you'll be able to access the num or name members directly, since all of the types have a consistent initial layout. If you need to access additional fields, you can cast st_TableBase to one of the "derived" types.

For more information on the sockaddr structures see http://www.retran.com/beej/sockaddr_inman.html.

查看更多
登录 后发表回答