C: Extrapolating type from void pointer

2019-01-18 23:14发布

Say a function takes a void pointer as an argument, like so: int func(void *p);
How can we determine or guess the type of what p is pointing to?

4条回答
▲ chillily
2楼-- · 2019-01-18 23:24

In general, you can't. In some cases, if there is a guarantee on what p points to, you may be able to look at the contents at and after that address to find out. Generally, your function should know what it's being passed, unless it just passes it along.

Data and function arguments in C are just a bunch of bits lumped together. Unless you use some of those bits to tell you what the bits are, there's no consistent way to identify it.

查看更多
手持菜刀,她持情操
3楼-- · 2019-01-18 23:25

Sure you can, and it's easy too. It's C, do whatever you want, how you want it.

Make a type system. Put everything you pass into a structure, make the first byte or two a magic number to determine what the structure contains beyond the magic number.

Make some functions to create/get/set/destroy the "typed variables".

Make some other functions to add and register new types at runtime.

Create a few defines to make it easier to read and typecast the structs.

Before you know it you will have a nice proprietary type system you can use for your projects, and it will always do EXACTLY what you want and need because YOU made it.

You could go crazy and grow it into a full object oriented like system. Or save yourself the work, and use the work of all the other people who already went crazy - http://en.wikipedia.org/wiki/GObject

查看更多
beautiful°
4楼-- · 2019-01-18 23:36

Short answer - you cannot.

In C there's no runtime time information unless you provide it, but look at the printf(3) family and see how easy it is to shoot yourself in the foot with mismatched format spec and actual argument type.

Type system is your friend. Use it.

查看更多
你好瞎i
5楼-- · 2019-01-18 23:41

I was confronted with a similar problem and I found myself having to write an instruction set for a programming language project. I came up against this problem because I had an array of pointers to functions so that functions could be enumerated and run in a for loop (for things like online help and syntax etc). For example:

struct List_Str  *(*InstructionSet[])(struct List_Str *ContextPrefix,struct List_Str *ContextSuffix)=
{

  AAVF,Add,AddEmotions,AddEmoDebug,AddScope,...

};

Now you could easily do the same thing with char * instead of struct List_Str * types, then convert all data into string format using snprintf and atoi and atof and other conversion functions. If you do a:

man isalpha

This shows you lots of functions in ctype.h that could give you ideas how to determine what type of data is held within the strings.

Folding all types into "stringy" format allows tremendous flexibility and regularity, but automagically converting the data from the strings to integers, floats etc, is arduous, but fruitful once the routines are librified.

If you intend to hold binary data, then you cannot use strings, since 0 chars can be inside the binary data and this confuses strlen functions. Furthermore, you have no idea of the length of what has been malloc'd once it leaves scope, so storing the length of the dereferenced data before the data is recommended in the first few bytes of char *.

One last thing, I wouldn't recommend storing data in void *, it's too vague. I recommend using char * as it's a bit more specific, can contain everything that void * can and the compiler will let you know beforehand if anything looks fishy.

查看更多
登录 后发表回答