iOS筆試知識點集錦

參考自:《鵝廠實習生客戶端筆試》

1.下列減少內存碎片的方法有哪些是正確的?

增加實際申請和釋放的次數
頻繁調用的子函數儘量使用棧內存
系統申請一大塊內存,自己實現內存分配和釋放,定時清理內存
降低虛擬內存的大小

解答:

答案2,3是正確的。屬於操作系統中內存管理的問題。

C/C++中的malloc/free是從堆中動態申請和釋放內存的,是非常耗時的;
棧內存速度比堆內存快,因爲棧結構簡單,只需要彈出或者入棧就可以移動指針了,而在堆中,需要查找空閒內存,申請內存等操作,所以比較慢;
分配一大塊內存池,然後自己進行管理,有經驗的程序員是可以做到的,比如在nginx中,它就首先分配了很多的內存,然後再重寫malloc/free進行自主管理的;
關於虛擬內存,肯定是越多越好啊,升級64位最顯著的優勢就是可以使用64EB的內存。

考點:Stack與Heap的區別:

這裏寫圖片描述

考點:虛擬內存(Virtual memory)

在32位Unix下,進程啓動後,可以獲取到4GB的虛擬內存,其中內核佔用1G,用戶佔用3G,虛擬內存是通過物理內存(physical memory)與交換空間(swap)進行分配的,它對於進程是透明的,系統通過地址轉換功能(比如MMU,內存管理單元)進行虛擬內存與實際內存的轉換。

什麼是內存碎片?

內部碎片: 線程佔用內存而不利用或者釋放的內存空間。
外部碎片: 內存空間太小以至於無法分配的內存空間。

2.以下哪些是HTTP協議裏面定義的URL組成部分:

schema
path
port
host
query-string
解答:

這道題答案是除第一個以外。考的是實際中對網絡編程的理解。

URL實際上就是是對資源的一種描述:

<scheme>://<host>:<port>/[<path>|<pathPrefix>|<pathPattern>]<query-string>

scheme 指協議類型,常見的協議類型有market,http,content,media,file,當然協議類型也可以自定義,比如簡書中使用的就是 jianshu作爲默認URL的。
注意這裏的 scheme 不是 schema

比如HTTP-GET的例子:

http://www.blackswift.com:8080/api/v2/getimagelist?limit=10

很顯然,這個HTTP例子中除了HTTP本身已經有了,其它所有的組成都有體現。

3.已知人臉檢測器的檢出率(人臉圖被檢測爲人臉的概率)爲90%,誤檢率(非人臉被檢測爲人臉的概率)爲1%. 請問當一張被人臉檢測器識別爲人臉時,該圖爲人臉圖的概率是多少?若給定一個圖片集中,其中20%的圖片爲人臉圖,80%的圖爲非人臉圖,當該集合中的某一張圖被人臉檢測器檢測爲人臉時,該圖爲人臉的概率又是多少?

  1. 無法確定, 45/47
  2. 90/91, 45/47
  3. 無法確定,90/91
  4. 90/91,90/91
    解答:

選擇1;

第一問,

A = P(圖片是人臉);
B = P(機器檢測出人臉);

P(B|A) = 90%;
P(B|~A) = 1%;

P(B) = P(B|A)xP(A) + P(B|~A)* P(~A) = 0.9A + 0.01(1-A);

根據貝葉斯公示:

P(A|B) = P(B|A) * P(A)/P(B)
= 0.9 * P(A)/(0.89A + 0.01)
A爲止,所以無法確定。

第二問,

P(A) = 0.2,代入完成。

4.iOS開發中,非ARC下這段代碼執行的結果是什麼?

//類似於Java,用註解定義接口
@interface OCObject : NSObject
-(void)printDescription;
@end

//接口的實現
@implementation OCObject
-(void)printDescription{
NSLog(@”OCObject printDescription!”);
}
@end

//手動分配內存,alloc並init
OCObject *obj = [[OCObject alloc]init];
//執行方法,performSelector類似於Java中的反射,也是在運行時找的。
[obj performSelector:@selector(printDescription) withObject:nil afterDelay:60];
[obj release];
1. 不會打出任何消息
2. 會輸出OCObject printDescription!
3. 會crash
4. 編譯不通過
解答:

答案是2

ARC是 Automatic Reference Counting,即自動引用計數器,在iOS開發中,蘋果不希望開發者控制內存,所以使用ARC幫助開發者在編譯的時候自動加上內存回收的代碼。

以下爲測試結果:

Xcode6.3/ARC on/iOS8.3下,編譯不通過,要求刪除release,刪除後編譯通過,輸出Log;

Xcode6.3/ARC off/iOS8.3下,編譯通過,輸出Log。

5.以下對C++(C++98標準)語言描述中正確的是

  1. C++提供了對全局對象初始化順序控制的機制
  2. C++沒有提供固定大小的整型
  3. C++支持多維數組
  4. C++支持類類型的成員常量
    解答:

答案是1 3 4

·全局對象如果有依賴的話,就需要對初始化順序進行控制,C++已經有了這個機制;
·C++中有int8_t,int16_t,int32_t, 甚至int64_t,所以是有固定大小的整型;
·多維數組肯定支持,連C語言都支持;
·類類型的成員常量是支持的,用const修飾。

6.請問下列代碼,當x =0x7c和x=0f2時,運行結果分別是什麼?

int main(){
    char x = 0xF2;
    int nConut = 0;
    //這裏的x 就是 x!= 0x00;
    for (; x; x>>=1) {
        ++nConut;
    }
    printf("nCount = %d ",nConut);
}

解答:

答案分別是7,死循環。

第一個是簡單二進制操作題目,用於判斷它有多少位。至於第二個,是負數。

這裏寫圖片描述

知識點:
負數右移是補1,最後就是0xffffffff了

11110010
11111001
11111100
11111110
11111111

由於-1始終不爲0,所以會死循環。

無符號右移(unsigned right shift)在iOS中是沒有的,在Java中是有的。

7.下列方法得到的NSString對象與衆不同的是:

NSString *str = @"Hello";
NSString *str2 = [NSString stringWithFormat:@"%s","Hello"];
NSString *str3 = [NSString stringWithFormat:@"%s","Hello"];
NSString *str4 = [[NSString alloc]initWithString:@"Hello"];

解答:

答案是第四個,它調用了malloc,是在堆中(運行時)申請的,需要手動釋放(如果沒有用arc的話),而其它幾個是編譯時(棧中)就已經固定在_DATA段了。

8.在一個路由表中,假設有下面三條路由:192.168.128.0/24, 192,168.130.0/24, 192.168.132.0/24,如果進行路由匯聚,能覆蓋這三條路由的地址是:

192.168.128.0/21
192.168.128.0/22
192.168.130.0/22
192.168.130.0/23
解答:

答案是第一個。

1100 0000.1010 1000.1000 0000.0000 0000
1100 0000.1010 1000.1000 0010.0000 0000
1100 0000.1010 1000.1000 0100.0000 0000
可以看出,公共節點在21位。

9.程序運行的結果是?

#include<stdio.h>

struct A
{
    unsigned char x;
    unsigned char y;
    int z;
};

int main(){

    struct A a;
    a.x = 10;
    a.y = 20;
    a.z = 30;
    *((int*)&a) = 0x010101ff;
    printf("%d,%d,%d,%d",sizeof(a),a.x,a.y,a.z);
    return 0;
}

解答:
8,255,1,30

本題有2個重點:

結構體對齊
指針類型轉換

在結構體對齊中,我們要知道,爲了提高內存讀取效率,需要把結構體中的成員按照2^n(Power-of-two)來進行對齊(align)的,對齊準則是

回到題目,我們可以看出,結構體是按照Int,也就是4byte來對齊的

這裏寫圖片描述

所以sizeof爲8.

接下來,是指針問題,我們先翻譯這句話

((int)&a) = 0x010101ff;

它實際上就是取a的地址,然後把a到(a+4)byte中的內容換成0x010101ff。僞代碼如下

a.x = (0x010101ff)&0xff;
a.y = (0x010101ff>>2)&0xff; //小端CPU的情況

a,z不受影響啦
也就是這樣

這裏寫圖片描述

10.在SQL語句中,與X BETWWEN 20 AND 30 等價的表達式是:__?

解答;

20<= x <= 30,是包括邊界的,最多可以取出11個數。

11.在iOS開發中,需要實踐一個簡單的http協議通訊,可用的工具/組件有?

BSD Socket API
CFSocket
NSStrem
NSSURLConnection
解答:

答案是NSSTream 與 NSSURLConnection。

前面兩個Socket是屬於傳輸層的,面向底層網絡連接,要是自己重寫一個HTTP那還不得累死。在Android中,有URLConnnection,OkHttp,Volley等組件。

12.下列關於棧的說法哪些是正確的?

  1. 棧是後進先出的
  2. 通常棧空間大小在編譯時指定,並在程序運行時由操作系統管理(分配,釋放等)
  3. 所有定義在函數內部的變量都是從棧上分配內存
  4. 棧的使用效率比堆高
  5. 棧內存具有讀,寫屬性
    解答:除了3是錯的,別的都是對的。注意函數內部的malloc。

13.二進制0.101001B等於十進制()?

0.640625D
0.620125D
0.820325D
0.804625D
解答:0.640625D。

1/2 + 1/8 + 1/64 

= 0.5 + 0.125 + 0.015625
= 0.640624D

14.關於數據類型的取值範圍,在Java中執行語句 byte b = (byte)128,請問b的值是多少?

  1. -1
  2. 128
  3. -128
  4. 出錯
    解答:

答案爲128;

第一,強制轉換實際上就是添加mask,僞代碼如下

b = 0x80;
b_new = 0x80 & 0xff;
第二,char與byte的區別(特指C中)

0x00 ~ 0x7f 0x80 ~ 0xff
byte 0 ~ 127 128 ~ 255
char 0 ~ 127 -128 ~ -1
如果我們把byte改成char,結果就是-128了,因爲java中的char是有符號而且是雙子節的。

15.網絡帶寬擁堵可能導致以下哪些問題?

  1. UDP丟包變嚴重
  2. tcp數據被寫亂
  3. tcp丟包
  4. tcp傳輸速度驟降
    解答:1 3 4

網絡擁塞一般是由三個原因照成:

存儲空間(緩存),比如緩存隊列滿了就會被路由器丟包;
帶寬不足,比如最近的出國帶寬就受到了不明干擾;
處理器不足,特別是在openwrt路由器上,由於MIPS的CPU性能優化不足,導致網速下降。
解決擁塞:

滿足上面三個短板
使用NetSpeeder,ARP等不良工具強制搶網速

16.下列函數的時間複雜度是

int foo(int n){
    int i = 1;
    while(1 <= n){
        i = i*2;
    }
    return 1;
}

解答:
答案是O(log2N),非常簡單。這裏的 i = i*2 可以用 i <<= 1來優化哦。

17.使用快速排序對{83,123,69,179,118,13,190}進行升序排序,請問如下那個是第一趟快排交換後的結果?

  1. {13,69,83,179,118,123,190}
  2. {13,83,69,179,118,123,190}
  3. {13,69,83,118,179,123,190}
  4. {13,123,69,179,118,83,190}
    解答:答案是 1

原理可以參考 http://me.dt.in.th/page/Quicksort/ 的 Partitioning

18.關於TCP和UDP協議的說法正確的有:

  1. TCP是面向連接的協議,而UDP是無連接的協議
  2. TCP建立連接過程中,協議棧需要進行三次握手,而關閉連接則需要進行4次握手;
  3. UDP協議常常用於容忍丟數據,但需要更高傳送性能的業務場景;
  4. UDP和TCP協議棧都具備保證數據包時序性的能力,並通過滑動窗口機制進行擁塞控制。
    解答:1 2 3

19.假設代碼如下:

#include<stdio.h>
#pragma pack(8)
struct X{
    uint8_t a;
    uint32_t b;
    uint16_t c;
};
#pragma pack()

int main(){
    struct X x;
    printf("%d\n",sizeof(x));
    return 0;
}

解答:

答案是12。同剛剛的那道結構體對齊的題目,公式如下

MIN(MAX(DataType),#pragram pack(8))
= MIN(8,8);
= 8;
所以以8byte爲準則進行對齊,它的內存佈局如下
這裏寫圖片描述
如果我們現在改一下結構體的佈局

struct X{
    uint8_t a;
    uint16_t c;
    uint32_t b;
};

它的佈局是這樣的


這樣,結構體的佔用就變少了,sizeof由12變成了8。

20.一顆二叉樹有5個節點,樹的形態有多少種?

  1. 38
  2. 42
  3. 46
  4. 58
    解答:42

考的是遞推。以根節點爲開始,按照左一右零,左一右一,左零右一的三個方向進行調用,網上有公式。

大題(60分鐘)

1.請儘可能多的列舉/描述出你所瞭解的個進程間通信機制已經對應的應用場景,各自的優缺點。

我只知道Android中的Binder;還有曾經學的管道,Socket。

2.已知結構體StructA定義如下

#include<stdio.h>
typedef struct _StruckA{
    unsigned int val1;
    unsigned char bSuccess;
    unsigned int val2;
    unsigned char bInitialize;
}structA, *pStructA;

int main(){
    structA a;
    a.val1 = 0x12345678;
    a.bSuccess = 0;
    a.val2 = 0xABCDEF01;
    a.bInitialize = 1;
    //請給出變量a在x86,x64下的內存分佈情況

    return 0;
}

解答:

!address 0x00 ~ 0x03 0x04 0x05 ~ 0x7 0x08 ~ 0x0b 0x0c 0x0d ~ 0x0f
value val1 bSuccess padding val2 bInitialize padding

還是按照4byte對齊,共16bype,具體原理我在前面的字節對其中已經講了

而且我沒有32位的機子測試啊,全是LP64的….運行以下代碼

printf("%d\n",sizeof(a));
printf("%p\n",&a);
printf("%p\n",&a.val1);
printf("%p\n",&a.bSuccess);
printf("%p\n",&a.val2);
printf("%p\n",&a.bInitialize);

Xcode6.3

16
0x7fff5fbff838
0x7fff5fbff838
0x7fff5fbff83c
0x7fff5fbff840
0x7fff5fbff844

Ubuntu14.10 x64

16
0x7fff652a4880
0x7fff652a4880
0x7fff652a4884
0x7fff652a4888
0x7fff652a488c

3.設計抽卡程序,策劃人員填寫物品出現概率,程序按照概率隨機抽出物品。配置表如下:

<data>
    <item id="1">10</item>
    <item id="2">50</item>
</data>

4.用C寫一個程序,得出當前系統的整型數字長(16位,32位,64位等),不能使用sizeof()

解答:

使用數組即可

#include<stdio.h>
unsigned int getSize(){
    int a[2] = {1,2};
    return (char*)(a+1) - (char*)a;
}

或者

unsigned int getSize(){
    int *a;
    return (char*)(a+1) - (char*)a;
}

5.在傳統的CS網絡模型中,server端需要控制請求量,對超過某個閥值的請求量直接拋棄或者返回錯誤,以保護自己(過載保護)。假設一個Server服務的能力爲1W Qps,設計一個過濾機制,對於超過服務能力的請求直接拋棄。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章