1. 程式人生 > >C 語言通過結構體成員獲得結構體指標

C 語言通過結構體成員獲得結構體指標

通過結構體成員拿到結構體的指標,是C語言實現繼承多型的基礎。面向物件C程式設計可以參看這裡OOC 面向物件C語言程式設計實踐。這裡詳細介紹這個核心的操作方法。

/**
 * Get struct pointer from member pointer
 */
#define StructFrom2(memberPtr, structType) \
	((structType*) ((char*) memberPtr - offsetof(structType, memberPtr)))


下面給出一個使用的例子。
typedef struct Drawable Drawable;  
struct  Drawable  
{  
     float positionX;  
     float positionY;  
};  

typedef struct Sprite Sprite;  
struct  Sprite  
{  
    Drawable drawable[1];  
};  

Sprite sprite[1];

Drawable* drawable = sprite->drawable;

Sprite* sprite = StructFrom2(drawable, Sprite);  

我們需要傳入成員變數的地址和結構體型別。這樣,首先使用offsetof標準庫函式,獲得這個成員變數的偏移量。在利用成員變數指標減去這個偏移量,就拿到了這個結構體物件的地址。這裡有兩個注意的地方。

第一,這裡成員變數的名稱,要和成員指標名字一致。因為offsetof引數需要的是成員變數名字。例子中drawable變數名和成員名是一樣的。

第二,成員變數地址,需要的是在結構體中的地址,這樣減去偏移量才是結構體物件地址。定義中我們使用drawable[1] 是一個小技巧,這樣drawable指標變數就是結構體中的地址。

第一種情況。

Sprite sprite[1];

Drawable* dd = sprite->drawable;
// 這是錯誤的
Sprite* sprite = StructFrom2(dd, Sprite);  

在定義中,drawable是成員的名字,所以offsetof中需要使用drawable,應該是這樣offsetof(Sprite, drawable)。我們如果定義了dd的變數offsetof是無法正常工作的。如果,某些特殊的情況,我們不能把變數的名字和成員定義的名字寫成一樣的。那麼我們就要提供,另外一個處理方法。如下。
/**
 * Get struct pointer from member pointer
 */
#define StructFrom3(memberPtr, structType, memberName) \
	((structType*) ((char*) memberPtr - offsetof(structType, memberName)))

這樣,我們可以把成員名字和變數名字同時傳入,就像這樣。StructFrom3(dd, Sprite, drawable)

第二種情況。

typedef struct Sprite Sprite;  
struct  Sprite  
{  
    Drawable drawable;  
};  

如果我們,這樣定義drawable不是以陣列的形式出現的。&sprite->drawable 獲得才是成員地址。

相關推薦

C 語言通過結構成員獲得結構指標

通過結構體成員拿到結構體的指標,是C語言實現繼承多型的基礎。面向物件C程式設計可以參看這裡OOC 面向物件C語言程式設計實踐。這裡詳細介紹這個核心的操作方法。 /** * Get struct pointer from member pointer */ #defin

c語言中的特殊符號(結構中)

結合 特殊 value -s height 間接尋址 出現 span size  在“結構”中出現的->運算符成為“右箭頭選擇”,可以用new_node->value = 10;來代替(*new_code).value = 10;即運算符->是運算符*和運

c語言_文件操作_FILE結構小解釋

hold 輸出 def 系統 span fopen 大小 round typedef 參考文檔來自:https://www.cnblogs.com/haore147/p/3648395.html 我們通過fopen返回一個文件指針(指向FILE結構體的指針)來進行文件操作。

C語言基礎知識(一)結構struct 和typedef struct區別

C與C++中struct 和typedef struct區別從三個方面對比 1、宣告變數方便: 在C語言中,常常見到typedef修飾結構體,如: #include<stdio.h> typedef struct _TEST { int value; char mat

C語言複習筆記(1)——結構

結構體 結構體宣告 結構體是一種由一序列的成員組成的型別,成員的儲存以順序分配於記憶體中(與聯合體相反,聯合體是由一個序列的成員組成的型別,成員儲存在記憶體中重疊)。 結構體的型別指定符與聯合體( union )型別指定符相同,只是所用的關鍵詞有別。 語法 str

計算機二級-C語言-程式填空題-190112記錄-結構的遍歷和結構的資料的交換處理,檔案的操作。

//程式設計題:學生的記錄由學號和成績組成,N名學生的資料已在主函式中放入結構體陣列s中,請編寫函式fun,它的功能是:把分數低的學生資料放在b所指的陣列中,注意:分數最低的學生可能不止一個,函式返回分數最低的學生人數。 //重難點:結構體的定義。結構體的使用。檔案指標的定義。對檔案的操作。輸出格式‘%4d

C語言分配動態二維陣列(結構實現)

#include<stdio.h> #include<stdlib.h> typedef struct { double **mat; int m; int n; }Matrix; void InitialMatrix(Matrix *T,in

菜鳥學習-C語言函式引數傳遞詳解-結構與陣列

C語言中結構體作為函式引數,有兩種方式:傳值和傳址。 1.傳值時結構體引數會被拷貝一份,在函式體內修改結構體引數成員的值實際上是修改呼叫引數的一個臨時拷貝的成員的值,這不會影響到呼叫引數。在這種情況下,涉及到結構體引數的拷貝,程式空間及時間效率都會受到影

C語言之運算符和條件結構

比較運算 第三名 user 石頭 年齡 pan 註意 break -1 表達式:是有操作數和運算符組成的。 操作數:常量、變量、子表達式 X=(x+2)*(y-2); 運算符: 賦值運算符:= 。其作用是做賦值運算,將等號後邊的值賦值給等號前邊的。 復合賦值運算符: +=

C語言 第五章 循環結構

i+1 1-1 之間 cat div toolbar print 所有 mage 一、for 二、while 三、do while 四、continue 五、break 一、for 請在屏幕上輸出1000個*號 printf("*****************

c語言實現基本的數據結構(六) 串

null cat ret pri include tchar 取字符 文件 子字符串 #include <stdio.h> #include <tchar.h> #include <stdlib.h> // TODO: 在此處引用

c語言第五章-循環結構I

log 初始化 表達 才會 包含 給定 重復 循環條件 表達式 需要多次重復執行一個或多個任務的問題考慮使用循環來解決while循環:格式:while(條件表達式){ 循環體 }循環三要素:初始化、條件表達式、增量條件表達式必須是可改變的量,否則可能形成死循

c語言第六章-循環結構II

while循環 程序 如果 初始化 應該 con class 語句 優先 for( 表達式1 ; 表達式2 ; 表達式3 ){ 語句;}for 循環與 while 循環類似,屬於先判斷後執行執行順序是:表達式1、表達式2、語句、表達式3-->表達

C語言實驗——判斷素數(迴圈結構

Problem Description 從鍵盤上輸入任意一個正整數,然後判斷該數是否為素數。 如果是素數則輸出"This is a prime." 否則輸出“This is not a prime.” Input 輸入任意一個正整數n(1 <= n <= 1000000)。

1117-C語言實驗——求絕對值(選擇結構)-JAVA

C語言實驗——求絕對值(選擇結構) Time Limit: 1000 ms Memory Limit: 65536 KiB Problem Description 從鍵盤上輸入任意一個整數,然後輸

C語言的那些事兒 (迴圈結構程式設計)

1.迴圈語句初認識:在不少實際問題中有許多具有規律性的重複操作,因此在程式中就需要重複執行某些語句。一組被重複執行的語句稱之為迴圈體,能否繼續重複,決定迴圈的終止條件。迴圈結構是在一定條件下反覆執行某段程式的流程結構,被反覆執行的程式被稱為迴圈體。迴圈語句是由迴圈體及迴圈的終止條件兩部

C語言第四章練習(選擇結構程式設計)

2018年11月16日 21:48:23 suaxpm 閱讀數:4 個人分類: IT

C語言實現一個鍵值對結構demo

主要思路是有兩個指標陣列,一個為key,一個為value,用索引一一對應實現一個key對應一個value。包括了增加和刪除,控制檯列印方法,現在仍有些指標指向記憶體類的bug需注意。這個程式嚴格來說還算不上雜湊。 #include<stdio.h>

C語言中的三種迴圈結構及其注意點

三種迴圈結構:  1)for ( ); while( ); do- while()三種。  2)for迴圈當中必須是兩個分號,千萬不要忘記。  3)寫程式的時候一定要注意,迴圈一定要有結束的條件,否則成了死迴圈。  4) do-while()迴圈的最後一個while();的分號一定不能夠丟。       do

結構成員結構指標初始化

#include<stdio.h>#include <stdlib.h>#include <string>struct student{   char *name;   int score;   struct student* next;