最近因為忙到一個不行,一整個一二月都處於忙碌狀態,雖說現在還在忙碌時期,但該交的都交了,剩下的都是在等時間了,所以,又能繼續寫文章拉:D
這一次我們討論幾個東西,一個是offsetof,一個是container_of,這兩個都是marco,offsetof是用來判斷結構體中成員的偏移位置,container_of是用來根據成員的地址來取得結構體的位址。
offsetof 的 Marco 定義如下 :
#define offsetof(type, member) (size_t)&(((type*)0)->member)
這邊有趣的地方,就在於將地址0強制轉換為type類型的指針,從而定位到member在結構中偏移的位置,編譯器會認為0是一個有效的地址,然後認為0是type指針的起始位置。
這樣講似乎有點玄,我們來寫一個簡單的例子來看,這樣就會比較有感覺了 :
#include <iostream>
using namespace std;
struct foo
{
char a;
char b[10];
char c;
};
int main() {
printf("offsetof(struct foo,a) is %d\n", (int)offsetof(struct foo, a));
printf("offsetof(struct foo,b) is %d\n", (int)offsetof(struct foo, b));
printf("offsetof(struct foo,c) is %d\n", (int)offsetof(struct foo, c));
return 0;
}
Output :
0
1
11
#include
#include
#define NAME_STR_LEN 32
#define offsetof(type, member) (size_t)&(((type*)0)->member)
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})
typedef struct student_info
{
int id;
char name[NAME_STR_LEN];
int age;
}student_info;
int main()
{
size_t off_set = 0;
off_set = offsetof(student_info, id);
printf("id offset: %u\n", off_set);
off_set = offsetof(student_info, name);
printf("name offset: %u\n", off_set);
off_set = offsetof(student_info, age);
printf("age offset: %u\n", off_set);
student_info *stu = (student_info *)malloc(sizeof(student_info));
stu->age = 10;
student_info *ptr = container_of(&(stu->age), student_info, age);
printf("age:%d\n", ptr->age);
printf("stu address:%p\n", stu);
printf("ptr address:%p\n", ptr);
return 0;
}
Output :
name offset : 4
age offset : 36
stu address : 0xabcdefg
ptr addrsss : 0xabcdefg
age : 10
接下來,我們來個考題吧
#define TTT(A, b) (&(((A *)0)->b))
typedef struct
{
char name[40];
int flags;
int maxPacketLen;
}ABCD;
以下expression的值為何?
auto n = TTT(ABCD,maxPacketLen);
ANS :
44
接下來,我們聊聊所謂的拷貝構造吧 !
所謂的拷貝構造,就是一種很特殊的構造含數,它再創件對象的時後,是使用同一個類中之前創建的對象來初始化新創建的對象,
而這玩意通常都是使用於 :
1. 通過使用另外一個同類型的對象來初始化新創建的對象。
2. 複製對象把他做為參數傳遞給函數。
3. 複製對象,並且從函數返回這個對象。
#include
using namespace std;
class Line
{
public:
int getLength(void);
Line(int len); //構造函數
Line(const Line &obj); //拷貝構造函數
~Line(); //析構函數
private:
int *ptr;
};
Line::Line(int len)
{
cout << "Line::Line(int len)" << endl;
ptr = new int;
*ptr = len;
}
Line::Line(const Line&obj)
{
cout << "Line::Line(const Line&obj)" << endl;
ptr = new int;
*ptr = *obj.ptr;
}
Line::~Line(void)
{
cout << "Line::~Line(void)" << endl;
delete ptr;
}
int Line::getLength()
{
return *ptr;
}
void display(Line obj)
{
cout << "Line size:" << obj.getLength() << endl;
}
int main()
{
Line line(10);
display(line);
return 0;
}
Output:
接下來,我們來看一個考題吧 !
有以下functions
class A
{
public:
int a;
int b;
}
void f1 (A*a);
void f2 (A a );
void f3 (A&a);
A objA;
請問以下何者會讓A的constructor被呼叫到 ?
a) f1(&objA);
b) f2(objA);
c) f3 (objA);
ans :
f2