* (const struct Class **) p = class;
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include <stdarg.h>
void test(void);
struct String {
const void * class; /* must be first */
char * text;
};
struct Class {
size_t size;
void (* test) (void);
};
void test(void)
{
printf("test for point.\n");
}
static const struct Class _String = {
sizeof(struct String),
test
};
const void * String = & _String;
/**
*
*/
int main(int argc, char const *argv[])
{
size_t stringSize = sizeof(struct String);
const struct Class * class = String;
void * p = calloc(1, class -> size);
assert(p);
* (const struct Class **) p = class;
struct String {
const void * class; /* must be first */
char * text;
};
struct String * p = (struct String *)calloc(1, sizeof(struct String));
return 0;
}
我们有如下定义:
struct String {
const void * class; /* must be first */
char * text;
};
struct Class {
size_t size;
void (* test) (void);
};
首先我们申请一个内存void * p = calloc(1, sizeof(struct String));
,这里很好理解,这个时候我们想让p
变成一个指向struct String
类型的一块内存,只需要申请的时候加上强制转换就可以了struct String * p = (struct String *)calloc(1, sizeof(struct String));
,这个时候p
就是一个指向struct String
类型元素的一个结构体指针。
接下来看下这个使用方法*(const struct Class **) p = class;
很多人看到第一眼的时候,第一眼就本能的将后面两个取址符与前面一个解引用相互抵消最终得出下面这样的结论,实际效果相当于:
(const struct Class *) p = class;
,你要是真的这样想就大错特错了。
这里的意思其实是如下图:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yFadxb79-1590937267126)(U:\linux-sys\ooc\doc\picture\指向指针的指解引用之后与指针的区别.png)]
在经过上述操作之后,p
指针指向了String
结构体,而* (const struct Class **) p = class;
的作用就是讲String
中的void *
类型的指针class
指向String
结构体,注意是结构体不是类型,解如图中那样,String
结构体其实是一个struct Class
类型的结构体指针。
static const struct Class _String = {
sizeof(struct String),
test
};
const void * String = & _String;
所以下面这个绝对不能使用取址和解引用相互抵消的方式进行代码走读,也不要新百度问答上那些讲的这不这样使用不能达到能将String结构体中的void *指针指向新申请内存的目的
const struct Class ** -- 告诉编译器这个指针是个二维指针,第一个指针是指向String结构体,结构体中又有两个指针,第二个指针说明的是取结构体指针中的指针,具体取得哪个指针就由前面给出的类型来决定了,这里取得是一个`struct Class`结构体指针。
因为这个时候取得是双重指针,有因为p本身又是指针,要想和class这个指针对应上,需要对指针进行一次解引用,这也就形成了下面这种方式,在C语言中实现取结构体指针中的指针的方式
* (const struct Class **) p = class;