最近因為忙到一個不行,一整個一二月都處於忙碌狀態,雖說現在還在忙碌時期,但該交的都交了,剩下的都是在等時間了,所以,又能繼續寫文章拉: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: 

image

 

 

 

 

 

接下來,我們來看一個考題吧 !

 

有以下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

 

 

 

 

 

 

 

 

 

arrow
arrow

    Eric 發表在 痞客邦 留言(4) 人氣()