今天做笔试题有几个问题:
1.内存拷贝函数memmove
void *memmove(void *dest, const void*src, size_t count)
{
assert((src != NULL) && (dest != NULL));
char*tmp, *s;
if (dest <= src)
{
tmp = (char*)dest;
s = (char*)src;
while (count--)
*tmp++ = *s++;
}
else
{
tmp = (char*)dest + count;
s = (char*)src + count;
while (count--)
*tmp-- = *s--;
}
return dest;
}
其实仔细一想是这么一个道理,memmove比memcpy函数更优化的地方在于他能够更好地处理内存重叠的问题。因此在else部分,也就是内存部分出现重叠时,代码需要从后面开始复制。
2.大小端字节序问题
TCP/IP协议栈使用的大端字节序,然而我们的机器可能是大端也可能是小端,因此经常需要有大小端转换的问题。同样的字节序之间的机器可以直接交流,不同字节序之间需要通过大小端转换。我们可以通过程序来判断我们当前的机器是大端还是小端,最常用的一种是union,一种是char*。
这里说一下char*的方法:long unsigned int i=0x12345678
因为char是一个字节,所以将char型量p指向i则p指向的一定是i的最低地址,在小端中最低地址为0x78,在大端中最低地址为0x12。
#include<iostream>
using namespace std;
int main()
{
unsigned long int i = 0x12345678;
char *p = (char*)&i;
if (*p == 0x78)
cout << "little endian" << endl;
else
cout << "big endian" << endl;
system("pause");
}
unsigned long int i = 0x12345678;
char *p = (char*)&i;
if (*p == 0x78)
cout << "little endian" << endl;
else
cout << "big endian" << endl;
system("pause");
}
上图为我电脑上的测试结果。小端的话每次网络字节序传到我电脑上都需要进行大小端转换。
大小端转换主要用到<<和>>位移符号,将小端转为大端需要进行左移,将大端转为小端需要进行右移。
在32位机器上:
uint EndianConvertLtoB(uint i)
{
uchar *p = (uchar *)&i;
return (uint *p << 24) + (uint *(p + 1) << 16) + (uint *(p + 2) << 8) + (uint *(p + 3));
}
3.这里再说说链表问题吧,不是笔试中遇到的,链表真的是要多做才能理解,像我这种数学渣机的人看了四五遍才稍微理解了指针指向问题。。。这里做个总结
链表指针前进:p=p->next;
链表增加一个节点p:p->next=pre->next; pre->next=p;
链表删除一个节点q:q=pre->next; pre->next=q->next; free(q);
链表创建:r->next=s; r=s; r->next=NULL;
链表合并: pc->next=pa; pc=pa; pa=pa->next;
pc->next=pb; pc=pb; pb=pb->next;
链表翻转:pr=p->next;p->next=q;q=p;p=pr;
以上代码要是你真的看得懂那就是缘分啊,毕竟是用意念写的代码。
4.再记录一些bigo的面试题,出了一道数组去重改编的题,有一些代码完整性的陷阱。还有客户端服务器端交互的基础函数,建议去看一些小型服务器源码。还出了一道STL的应用,要用到辅助的数据结构。