我正在使用包含此代码的库(我已删除了不相关的部分)
// Represents user-defined data
typedef char* aiUserData;
...
struct aiFile
{
// Callback to write to a file
aiFileReadProc ReadProc;
// Callback to retrieve the current position of
// the file cursor (ftell())
aiFileTellProc TellProc;
...
// User-defined, opaque data
aiUserData UserData;
};
我需要使用最后一个struct属性UserData
。为此目的使用结构会很方便,但是正如人们在第一行中看到的那样,UserData被声明为类型char *
。我读到char *
与void *
类似的地方。这是否意味着我可以做类似的事情:
.UserData = &MyDataStruct;
或者这不安全吗?
答案 0 :(得分:2)
图书馆设计得很糟糕,应该是void *
。
您可以合法地将任何指针转换为void *
,并将void *
转换为char *
,这样就可以了。
设置指针时,必须强制转换为char *
:
static struct mydata {
float pi;
} data; /* This is what we want to store. */
struct aiFile whatever;
whatever.UserData = (char *) &data;
以后当你想使用指针时,你必须进行反向投射:
struct mydata *d = (struct mydata *) whatever.UserData;
在实践中,你当然也会typedef
struct mydata
;为简洁起见,我省略了它。
如果图书馆做了正确的事并且使用了void *
,则无需进行任何投射。
答案 1 :(得分:1)
是的,我们可以认为这是安全的。
建议保存"用户数据",因此我们可以假设底层库不会使用它,您可以将指针传递给您喜欢的任何内容:
.UserData = (char *)&MyDataStruct;
完全取决于你在另一端正确解释它,即在这种情况下作为你的数据结构。
答案 2 :(得分:0)
允许字符指针别名为任何其他指针类型。
如果将.UserData
指针强制转换为正确的类型(typeof MyDataStruct),则可以使用它指向的对象。
只要指针指向有效内存,也可以在不进行转换的情况下取消引用字符指针。记忆的价值是另一个问题,你应该正确使用它。
引用为什么允许这样做:
6.5。 p7对象的存储值只能由具有其中一个的左值表达式访问 以下类型:
- 与对象的有效类型兼容的类型,
- 与对象的有效类型兼容的类型的限定版本
- 对应于有效类型的有符号或无符号类型 对象,
- 对应于合格版本的有符号或无符号类型的类型 有效的对象类型,
- 包含其中一种上述类型的聚合或联合类型 成员(包括,递归地,子集合或包含的联合的成员),或
- 字符类型。
和
6.2.5。 p28指向void的指针应具有与a相同的表示和对齐要求 指向字符类型的指针
6.3.2.3。 p1指向void的指针可以转换为指向任何对象类型的指针。指向的指针 任何对象类型都可以转换为指向void的指针,然后再返回;结果应该 比较等于原始指针。
因此,char指针可以存储任何类型的指针,与void指针的方式相同。
当然,正如您提到的那样,对于函数指针,这一切都不成立。你不能把它们和其他类型混合在一起。