dugu-ghs

 

 1 /*
 2      * create a Link Level name for this device
 3      */
 4     unitname = sprint_d((u_int)ifp->if_unit, workbuf, sizeof(workbuf));
 5     namelen = strlen(ifp->if_name);
 6     unitlen = strlen(unitname);
 7 #define _offsetof(t, m) ((int)((caddr_t)&((t *)0)->m))
 8     masklen = _offsetof(struct sockaddr_dl, sdl_data[0]) +
 9                    unitlen + namelen;
10     socksize = masklen + ifp->if_addrlen;
11 #define ROUNDUP(a) (1 + (((a) - 1) | (sizeof(long) - 1)))
12     socksize = ROUNDUP(socksize);
13     if (socksize < sizeof(*sdl))
14         socksize = sizeof(*sdl);
15     ifasize = sizeof(*ifa) + 2 * socksize;

图3-35 if_attach函数:计算链路层地址大小

 

个人c没怎么学,感觉很吃力。

第一个问题是sprint_d函数是什么?找到源代码是

static char *
sprint_d(n, buf, buflen)
	u_int n;
	char *buf;
	int buflen;
{
	register char *cp = buf + buflen - 1;

	*cp = 0;
	do {
		cp--;
		*cp = "0123456789"[n % 10];   //不错的代码。呵呵
		n /= 10;
	} while (n != 0);
	return (cp);
}

 其实,sprint_d就是把u_int类型的数转化为字符串。

第二个问题是,这个第七行的宏函数是神马东西?

#define _offsetof(t, m) ((int)((caddr_t)&((t *)0)->m))

1. caddr_t是核心地址,一般被定义为char*;

2.  &((t *)0)->m)这是神马,其实&在这是取地址符,(t *)0是对编译器说:“我这是t结构的指针,地址是0”,所以我们获得的t指针的首地址是0(或者说基址是0)。所以,&((t *)0)->m)就是m在结构t中的偏移量了。

 #define ROUNDUP(a) (1 + (((a) - 1) | (sizeof(long) - 1)))

这个就是把a上舍入为一个长整数。sizeof(long)一般为4(有的时候是8),所以(sizeof(long) - 1)的二进制码为11,所以前面的((a) - 1)不管是什么,

(((a) - 1) | (sizeof(long) - 1))最后的结果的最低的2位的二进制码都是11。再加上1所以ROUNDUP(a)的结果是把a的第二位变成00且往第三位进1。产生的结果是ROUNDUP(a)永远是4的倍数,例如1--4,2--4,3--4,5---8,6---8,11---12,15--16,等等、、、

分类:

技术点:

相关文章: