復合語句表示式的高階用法

2021-10-17 11:03:42 字數 2173 閱讀 1137

我在《c和指標》閱讀筆記(4)一文中詳細介紹了語句表示式操作符之間的關係,在c語言中,語句是由表示式和(或)分號組成表示式是由識別符號或操作符組成。本文再深入一步,介紹一種更複雜一點兒的用法:復合語句作為表示式,然後引出乙個常用的編碼技巧。

在gnu c中,將復合語句通過小括號括起來後,可以當做表示式。這樣的方式可使表示式完成更複雜的邏輯:如迴圈、分支、使用區域性變數。

#define container_of(ptr, type, member) ()
container_of巨集的作用是由結構體成員的位址來獲取結構體的首位址。暫時不關注巨集的具體內容(先賣個關子),僅看其輪廓,可以發現#define container_of(ptr, type, member) ({}),本文中將({})稱為復合語句表示式。既然是表示式,那表示式的值又是什麼呢?

/*

* ()

* ()

* * 整個復合語句表示式的值為expressionn的值

*/

所以,container_of 復合語句表示式的值 是(type *)( (char *)__mptr - offsetof(type,member) );的結果。

搞清楚了整體輪廓,接下來再講解細節。

/*

/usr/lib/gcc/x86_64-linux-gnu/7/include/stddef.h:417

#define offsetof(type, member) __builtin_offsetof (type, member)

*/// offsetof的本質邏輯如下:

//#define offsetof(type, member) (size_t)&(((type*)0)->member)

// 獲取結構體成員在結構體中的偏移

// ((type*)0), 將0強轉為指向type型別的指標

// &(((type*)0)->member), 獲取成員member的位址;由於((type*)0)的位址為0, 那麼member的位址即為其在結構體中的偏移

// 由結構體成員的位址來獲取結構體的首位址

#define container_of(ptr, type, member) ()

// ptr 表示結構體成員的位址

// type 表示結構體型別

// member 表示成員名, ptr和member代表相同成員

// typeof( ((type *)0)->member ) 獲取member的資料型別

// typeof( ((type *)0)->member ) *__mptr 定義乙個member資料型別的指標

// const typeof( ((type *)0)->member ) *__mptr = (ptr); 儲存ptr位址

// ( (char *)__mptr - offsetof(type,member) ) ptr的位址 減去member的偏移量, 即得到結構體的位址

// (type *)( (char *)__mptr - offsetof(type,member) ) 再將位址強轉為結構體指標

注意,如果使用g++ std=c++11編譯,需要將typeof改為decltype。當然,使用gcc編譯時沒有問題。

#include

#include

#include

#include

// include offsetof(type, member)

typedef

struct

com_queue_t;

typedef

struct _sample_bgra_queue_s

sample_bgra_queue_t;

void

test_offset()

intmain

(int argc,

char

** ar**)

參考:

復合lambda表示式

複習 public static void main string args 用lambda表示式 因為編譯器會自動根據 上下文推測出資料型別因此 collections.sort list,first,second first.getcolor compareto second.getcolor ...

1 2復合表示式與if語句書寫技巧

復合表示式由常量 變數 函式和運算子組成書寫應注意 1 不要過於複雜 如 x y z a i c 2 不要與數學表示式混淆 如 if x3 運算子優先順序和結合性直對結果的影響 4 表示式中有些部分可能沒參加運算 如 int a 1,b 2 if acout 輸出結果為1 aif語句書寫技巧與注意問...

正規表示式高階用法

1.獲取匹配 獲取這個匹配結果 可以使用 num 代替這個匹配的結果,可以用來實現替換功能。獲取這個匹配結果 pattern 2.非獲取匹配 和獲取匹配相反,不獲取匹配結果 pattern 以下四種預查方式都是非獲取匹配 1.正向肯定預查 與它前面的匹配表示式銜接,並通過它自己的表示式篩選前面的匹配...