* (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;