1. 程式人生 > >C++-Bigo筆試題

C++-Bigo筆試題

今天做筆試題有幾個問題:

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的應用,要用到輔助的資料結構。