1、 數組a[N],存放了1至N-1個數,其中某個數重復一次。寫一個函數,找出被重復的數字時間復雜度必須為o(N)函數原型:
int find(int a[],int n){
int temp[n]={0};
int i;
for(i=0;i<n;i++){
if(temp[a[i]] != 0){
return a[i];
}else{
temp[a[i]]=1;
}
}
}
2、一語句實現x是否為2的若干次冪的判斷
int i = 512;
cout << ((i & (i - 1)) ? false : true) << endl;
按位與運算符a&b,對b中為1的位如果a中也為1則保留,a中其余位全部置0,剩下的a即為結果也可以理解為保留a中與b中位1對應的位,其余置0。其余按位運算符類似,將a與b按位做相應運算,所得值即結果。
3、
char str1[] = "abc";
char str2[] = "abc";
const char str3[] = "abc";
const char str4[] = "abc";
const char *str5 = "abc";
const char *str6 = "abc";
char *str7 = "abc";
char *str8 = "abc";
cout << ( str1 == str2 ) << endl;
cout << ( str3 == str4 ) << endl;
cout << ( str5 == str6 ) << endl;
cout << ( str7 == str8 ) << endl;
結果是:0 0 1 1
解答:str1,str2,str3,str4是數組變量,它們有各自的內存空間;而str5,str6,str7,str8是指針,它們指向相同的常量區域。注意C語言不是這樣的。常量的地址也不一樣。
4、指針的引用......
main()
{
int a[5]={1,2,3,4,5};
int *ptr=(int *)(&a+1);
printf("%d,%d",*(a+1),*(ptr-1));
}
輸出:2,5
&a是數組指針,其類型為int (*)[5];而指針加1要根據指針類型加上一定的值,不同類型的指針+1之後增加的大小不同。a是長度為5的int數組指針,所以要加5*sizeof(int) 。所以ptr實際是a[5]。但是prt與(&a+1)類型是不一樣的(這點很重要),所以prt-1只會減去sizeof(int*)。a,&a的地址是一樣的,但意思不一樣,a是數組首地址,也就是a[0]的地址,&a是對象(數組)首地址,a+1是數組下一元素的地址,即a[1],&a+1是下一個對象的地址,即a[5].
5、死鎖的4個必要條件
互斥、請求保持、不可剝奪、環路
6、死鎖的處理
鴕鳥策略、預防策略、避免策略、檢測與解除死鎖
7、操作系統中進程調度策略有哪幾種?
FCFS(先來先服務),優先級,時間片輪轉,多級反饋
8、tcp/udp是屬於哪一層?tcp/udp有何優缺點?
tcp /udp屬於運輸層
TCP 服務提供了數據流傳輸、可靠性、有效流控制、全雙工操作和多路復用技術等。與TCP 不同,UDP 並不提供對IP 協議的可靠機制、流控制以及錯誤恢復功能等。由於UDP 比較簡單,UDP 頭包含很少的字節,比TCP 負載消耗少。
tcp: 提供穩定的傳輸服務,有流量控制,缺點是包頭大,冗余性不好
udp: 不提供穩定的服務,包頭小,開銷小
9、(void *)ptr 和(*(void**))ptr的結果是否相同?其中ptr為同一個指針。
是一樣的。
第一個沒問題 就是把ptr強制轉化為指向空類型的指針。第二個(*(void**))ptr 先看裡面的 這是轉化成指向void指針的指針 也就是二級指針。再在前面加上*就是取內容 那麼內容也是個指針。這個指針是指向空類型的 所以強制轉化後和第一個是一樣的。
10、要對絕對地址0x100000賦值怎麼做?要是想讓程序跳轉到絕對地址是0x100000去執行,應該怎麼做?
(unsigned int*)0x100000 = 1234
首先要將0x100000強制轉換成函數指針,即: (void (*)())0x100000。然後再調用它:
*((void (*)())0x100000)();
用typedef可以看得更直觀些: typedef void(*)() voidFuncPtr; *((voidFuncPtr)0x100000)();
本篇博客出自 阿修羅道