我正在为一个类项目编程一个简单的包嗅探器。有一段时间,我遇到了一个问题,一个包的源和目的地似乎是相同的。例如,以太网帧的源和目的地将始终是相同的MAC地址。我定制了ether_ntoa(char *)
,因为Windows不像Linux那样有ethernet.h
。代码段如下:
char *ether_ntoa(u_char etheraddr[ETHER_ADDR_LEN])
{
int i, j;
char eout[32];
for(i = 0, j = 0; i < 5; i++)
{
eout[j++] = etheraddr[i] >> 4;
eout[j++] = etheraddr[i] & 0xF;
eout[j++] = ':';
}
eout[j++] = etheraddr[i] >> 4;
eout[j++] = etheraddr[i] & 0xF;
eout[j++] = '\0';
for(i = 0; i < 17; i++)
{
if(eout[i] < 10)
eout[i] += 0x30;
else if(eout[i] < 16)
eout[i] += 0x57;
}
return(eout);
}
我通过使用
malloc()
让编译器分配内存来解决这个问题(即,我使用char eout[32]
而不是char * eout; eout = (char *) malloc (32);
)。但是,我认为编译器在编译时为一个char数组指定不同的内存位置。这不正确吗? 最佳答案
正如其他人指出的,您不能返回指向具有自动存储持续时间的对象的指针——当eout
超出范围时,它不再存在。GCC实际上警告您:
ether_ntoa.c: In function ‘ether_ntoa’:
ether_ntoa.c:26: warning: function returns address of local variable
实现所需结果的通常方法是让调用者负责分配目的地。例如:
int ether_ntoa(unsigned char etheraddr[ETHER_ADDR_LEN], char *dest, size_t len)
{
return snprintf(dest, len, "%02x:%02x:%02x:%02x:%02x:%02x",
(unsigned)etheraddr[0],
(unsigned)etheraddr[1],
(unsigned)etheraddr[2],
(unsigned)etheraddr[3],
(unsigned)etheraddr[4],
(unsigned)etheraddr[5]);
}
(还要注意,您的手工编码转换例程可以替换为一个简单的
snprintf()
调用)。你可以这样称呼它:char eout[32];
ether_ntoa(etheraddr, eout, sizeof eout);
/* Converted address is now in eout */
Linux上的
ether_ntoa()
函数使用不同的方法-它将函数中的缓冲区声明为static
。如果您这样做了,那么您的eout
将在程序的生命周期内有效,因此您可以返回指向它的指针。缺点是只有一个eout
-每次调用ether_ntoa
,它将覆盖前一个。