一、(一共三十題)
1.main()
{
int a[5]={1,2,3,4,5};
int *ptr=(int *)(&a+1);
printf("%d,%d",*(a+1),*(ptr-1));
}
答案:2,5
*(a+1)就是a[1],*(ptr-1)就是a[4],執行結果是2,5。a+1不是首地址+1,系統會認為加一個a數組的偏移,是偏移了一個數組的大小(本例是5個int)
int *ptr=(int *)(&a+1);
則ptr實際是&(a[5]),也就是a+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].
2.以下為Windows NT下的32位C++程序,請計算sizeof的值
void Func ( char str[100])
{sizeof( str ) = ?}
void *p = malloc( 100 );
sizeof ( p ) = ?
答案:sizeof( str )、sizeof ( p )都為4。
3.還是考指針,不過我對cocoa的代碼還是不太熟悉大概是這樣的- NSString *getNSString(void)
{
NSString *output=@"Thisis a main test\n";
return output;
}
-main(void)
{NSString *a=@"Main";
NSString *aString = [NSStringstringWithString:@"%@",getNSString(a)];NSLog(@"%@\n", aString);
}
答案:最后問輸出的字符串:NULL,output在函數返回后,內存已經被釋放。
4.用預處理指令#define聲明一個常數,用以表明1年中有多少秒(忽略閏年問題)寫一個"標準"宏MIN,這個宏輸入兩個參數并返回較小的一個。
答案:#defineSECONDS_PER_YEAR (60 * 60 * 24 * 365)UL
5.寫一個委托的interface
答案:@protocol MyDelegate;
@interface MyClass: NSObject
{
id delegate;
}
//委托方法
@protocol?MyDelegate
- (void)didJobs:(NSArray*)args;
@end
6.寫一個NSString類的實現-(id)initWithCString:(const char *)nullTerminatedCStringencoding:(NSStringEncoding)encoding; -(void)dealloc;
答案:+ (id) stringWithCString:(const char*)nullTerminatedCString
encoding: (NSStringEncoding)encoding
{
NSString*obj;
obj = [self allocWithZone:NSDefaultMallocZone()];
obj = [obj initWithCString:nullTerminatedCString encoding: encoding];
return AUTORELEASE(obj);
}
7.obj-c有多重繼承么?不是的話有什么替代方法?
答案:cocoa中所有的類都是NSObject的子類,多繼承在這里是用protocol委托代理來實現的,你不用去考慮繁瑣的多繼承,虛基類的概念.ood的多態特性在obj-c中通過委托來實現.
8.obj-c有私有方法么?私有變量呢
答案:objective-c -類里面的方法只有兩種,靜態方法和實例方法
在Objective‐C中,所有實例變量默認都是受保護的,所有實例方法默認都是公有的
9.關鍵字const有什么含意?關鍵字volatile有什么含意?并給出三個不同的例子。static關鍵字的作用,extern "C"的作用
答案:const意味著"只讀",聲明一個參數為常量是為了告訴了用戶這個參數的應用目的。
關鍵字const的作用是為給讀你代碼的人傳達非常有用的信息,實際上,聲明一個參數為常量是為了告訴了用戶這個參數的應用目的。如果
你曾花很多時間清理其它人留下的垃圾,你就會很快學會感謝這點多余的信息。(當然,懂得用const的程序員很少會留下的垃圾讓別人來清
理的。)
通過給優化器一些附加的信息,使用關鍵字const也許能產生更緊湊的代碼。
合理地使用關鍵字const可以使編譯器很自然地保護那些不希望被改變的參數,防止其被無意的代碼修改。簡而言之,這樣可以減少bug的出現。
(1)欲阻止一個變量被改變,可以使用const關鍵字。在定義該const變量時,通常需要對它進行初
始化,因為以后就沒有機會再去改變它了;
(2)對指針來說,可以指定指針本身為const,也可以指定指針所指的數據為const,或二者同時指
定為const;
(3)在一個函數聲明中,const可以修飾形參,表明它是一個輸入參數,在函數內部不能改變其值;
(4)對于類的成員函數,若指定其為const類型,則表明其是一個常函數,不能修改類的成員變量;
(5)對于類的成員函數,有時候必須指定其返回值為const類型,以使得其返回值不為“左值”。
static關鍵字的作用:
(1)函數體內static變量的作用范圍為該函數體,不同于auto變量,該變量的內存只被分配一次,
因此其值在下次調用時仍維持上次的值;
(2)在模塊內的static全局變量可以被模塊內所用函數訪問,但不能被模塊外其它函數訪問;
(3)在模塊內的static函數只可被這一模塊內的其它函數調用,這個函數的使用范圍被限制在聲明
它的模塊內;
(4)在類中的static成員變量屬于整個類所擁有,對類的所有對象只有一份拷貝;
(5)在類中的static成員函數屬于整個類所擁有,這個函數不接收this指針,因而只能訪問類的static成員變量。
extern "C"的作用
(1)被extern
"C"限定的函數或變量是extern類型的;
extern是C/C++語言中表明函數和全局變量作用范圍(可見性)的關鍵字,該關鍵字告訴編譯器,
其聲明的函數和變量可以在本模塊或其它模塊中使用。
(2)被extern
"C"修飾的變量和函數是按照C語言方式編譯和連接的;
extern "C"的慣用法
(1)在C++中引用C語言中的函數和變量,在包含C語言頭文件(假設為cExample.h)時,需進行下列處理:
extern "C"
{#include "cExample.h"}
而在C語言的頭文件中,對其外部函數只能指定為extern類型,C語言中不支持extern "C"聲明,在.c文件中包含了extern "C"時會出現編譯語法錯誤。
(2)在C中引用C++語言中的函數和變量時,C++的頭文件需添加extern "C",但是在C語言中不
能直接引用聲明了extern "C"的該頭文件,應該僅將C文件中將C++中定義的extern "C"函數聲明為extern類型。
10.為什么標準頭文件都有類似以下的結構?#ifndef __INCvxWorksh#define __INCvxWorksh#ifdef __cplusplusextern "C" {#endif/*...*/#ifdef __cplusplus}#endif#endif /*__INCvxWorksh */
答案:顯然,頭文件中的編譯宏“#ifndef __INCvxWorksh、#define __INCvxWorksh、#endif”的作用是防止該頭文件被重復引用。
11.#import跟#include的區別,@class呢?
答案:@class一般用于頭文件中需要聲明該類的某個實例變量的時候用到,在m文件中還是需要使用#import而#import比起#include的好處就是不會引起交叉編譯
12.MVC模式的理解
答案:MVC設計模式考慮三種對象:模型對象、視圖對象、和控制器對象。模型對象代表特別的知識和專業技能,它們負責保有應用程序的數據和定義操作數據的邏輯。視圖對象知道如何顯示應用程序的模型數據,而且可能允許用戶對其進行編輯。控制器對象是應用程序的視圖對象和模型對象之間的協調者。
13.線程與進程的區別和聯系?線程是否具有相同的堆棧? dll是否有獨立的堆棧?
答案:進程和線程都是由操作系統所體會的程序運行的基本單元,系統利用該基本單元實現系統對應用的并發性。
進程和線程的主要差別在于它們是不同的操作系統資源管理方式。進程有獨立的地址空間,一個進程崩潰后,在保護模式下不會對其它進程產生影響,而線程只是一個進程中的不同執行路徑。線程有自己的堆棧和局部變量,但線程之間沒有單獨的地址空間,一個線程死掉就等于整個進程死掉,所以多進程的程序要比多線程的程序健壯,但在進程切換時,耗費資源較大,效率要差一些。但對于一些要求同時進行并且又要共享某些變量的并發操作,只能用線程,不能用進程。
14.列舉幾種進程的同步機制,并比較其優缺點。進程之間通信的途徑進程死鎖的原因死鎖的4個必要條件死鎖的處理
答案:同步機制:原子操作,信號量機制,自旋鎖,管程,會合,分布式系統
進程之間通信的途徑:共享存儲系統消息傳遞系統管道:以文件系統為基礎
進程死鎖的原因:資源競爭及進程推進順序非法
死鎖的4個必要條件:互斥、請求保持、不可剝奪、環路
死鎖的處理:鴕鳥策略、預防策略、避免策略、檢測與解除死鎖
15.堆和棧的區別
答案:管理方式:對于棧來講,是由編譯器自動管理,無需我們手工控制;對于堆來說,釋放工作由程序員控制,容易產生memory leak。
申請大小:棧:在Windows下,棧是向低地址擴展的數據結構,是一塊連續的內存的區域。這句話的意思是棧頂的地址和棧的最大容量是系統預先規定好的,在WINDOWS下,棧的大小是2M(也有的說是1M,總之是一個編譯時就確定的常數),如果申請的空間超過棧的剩余空間時,將提示overflow。因此,能從棧獲得的空間較小。
堆:堆是向高地址擴展的數據結構,是不連續的內存區域。這是由于系統是用鏈表來存儲的空閑內存地址的,自然是不連續的,而鏈表的遍歷方向是由低地址向高地址。堆的大小受限于計算機系統中有效的虛擬內存。由此可見,堆獲得的空間比較靈活,也比較大。
碎片問題:對于堆來講,頻繁的new/delete勢必會造成內存空間的不連續,從而造成大量的碎片,使程序效率降低。對于棧來講,則不會存在這個問題,因為棧是先進后出的隊列,他們是如此的一一對應,以至于永遠都不可能有一個內存塊從棧中間彈出
分配方式:堆都是動態分配的,沒有靜態分配的堆。棧有2種分配方式:靜態分配和動態分配。靜態分配是編譯器完成的,比如局部變量的分配。動態分配由alloca函數進行分配,但是棧的動態分配和堆是不同的,他的動態分配是由編譯器進行釋放,無需我們手工實現。
分配效率:棧是機器系統提供的數據結構,計算機會在底層對棧提供支持:分配專門的寄存器存放棧的地址,壓棧出棧都有專門的指令執行,這就決定了棧的效率比較高。堆則是C/C++函數庫提供的,它的機制是很復雜的。
16.什么是鍵-值,鍵路徑是什么
答案:模型的性質是通過一個簡單的鍵(通常是個字符串)來指定的。視圖和控制器通過鍵來查找相應的屬性值。在一個給定的實體中,同一個屬性的所有值具有相同的數據類型。鍵-值編碼技術用于進行這樣的查找—它是一種間接訪問對象屬性的機制。
鍵路徑是一個由用點作分隔符的鍵組成的字符串,用于指定一個連接在一起的對象性質序列。第一個鍵的性質是由先前的性質決定的,接下來每個鍵的值也是相對于其前面的性質。鍵路徑使您可以以獨立于模型實現的方式指定相關對象的性質。通過鍵路徑,您可以指定對象圖中的一個任意深度的路徑,使其指向相關對象的特定屬性。
17.c和obj-c如何混用
答案:1)obj-c的編譯器處理后綴為m的文件時,可以識別obj-c和c的代碼,處理mm文件可以識別obj-c,c,c++代碼,但cpp文件必須只能用c/c++代碼,而且cpp文件include的頭文件中,也不能出現obj- c的代碼,因為cpp只是cpp。
2)在mm文件中混用cpp直接使用即可,所以obj-c混cpp不是問題
3)在cpp中混用obj- c其實就是使用obj-c編寫的模塊是我們想要的。
如果模塊以類實現,那么要按照cpp class的標準寫類的定義,頭文件中不能出現obj-c的東西,包括#import cocoa的。實現文件中,即類的實現代碼中可以使用obj-c的東西,可以import,只是后綴是mm。如果模塊以函數實現,那么頭文件要按c的格式聲明函數,實現文件中,c++函數內部可以用obj-c,但后綴還是mm或m。
總結:只要cpp文件和cpp include的文件中不包含obj-c的東西就可以用了,cpp混用obj-c的關鍵是使用接口,而不能直接使用實現代碼,實際上cpp混用的是obj-c編譯后的o文件,這個東西其實是無差別的,所以可以用。obj-c的編譯器支持cpp.
18.目標-動作機制
答案:目標是動作消息的接收者。一個控件,或者更為常見的是它的單元,以插座變量(參見"插座變量"部分)的形式保有其動作消息的目標。
動作是控件發送給目標的消息,或者從目標的角度看,它是目標為了響應動作而實現的方法。程序需要某些機制來進行事件和指令的翻譯。這個機制就是目標-動作機制。
19.cocoa touch框架
答案:iPhone OS應用程序的基礎Cocoa Touch框架重用了許多Mac系統的成熟模式,但是它更多地專注于觸摸的接口和優化。UIKit為您提供了在iPhone OS上實現圖形,事件驅動程序的基本工具,其建立在和Mac OS X中一樣的Foundation框架上,包括文件處理,網絡,字符串操作等。
Cocoa Touch具有和iPhone用戶接口一致的特殊設計。有了UIKit,您可以使用iPhone OS上的獨特的圖形接口控件,按鈕,以及全屏視圖的功能,您還可以使用加速儀和多點觸摸手勢來控制您的應用。
各色俱全的框架除了UIKit外,Cocoa Touch包含了創建世界一流iPhone應用程序需要的所有框架,從三維圖形,到專業音效,甚至提供設備訪問API以控制攝像頭,或通過GPS獲知當前位置。Cocoa Touch既包含只需要幾行代碼就可以完成全部任務的強大的Objective-C框架,也在需要時提供基礎的C語言API來直接訪問系統。這些框架包括:
Core Animation:通過Core Animation,您就可以通過一個基于組合獨立圖層的簡單的編程模型來創建豐富的用戶體驗。
Core Audio:Core Audio是播放,處理和錄制音頻的專業技術,能夠輕松為您的應用程序添加強大的音頻功能。
Core Data:提供了一個面向對象的數據管理解決方案,它易于使用和理解,甚至可處理任何應用或大或小的數據模型。
下面是Cocoa Touch中一小部分可用的框架:
音頻和視頻:Core Audio、OpenAL、Media Library、AV Foundation
數據管理:Core Data、SQLite
圖形和動畫:Core Animation、OpenGL ES、Quartz 2D
網絡/li>:onjour、WebKit、BSD Sockets
用戶應用:Address Book、Core Location、ap Kit、tore Kit
20.objc的內存管理
答案:1、如果您通過分配和初始化(比如[[MyClass alloc]
init])的方式來創建對象,您就擁有這個對象,需要負責該對象的釋放。這個規則在使用NSObject的便利方法new時也同樣適用。
2、如果您拷貝一個對象,您也擁有拷貝得到的對象,需要負責該對象的釋放。
3、如果您保持一個對象,您就部分擁有這個對象,需要在不再使用時釋放該對象。反過來,如果您從其它對象那里接收到一個對象,則您不擁有該對象,也不應該釋放它(這個規則有少數的例外,在參考文檔中有顯式的說明)。
21.自動釋放池是什么,如何工作
答案:當您向一個對象發送一個autorelease消息時,Cocoa就會將該對象的一個引用放入到最新的自動釋放池。它仍然是個正當的對象,因此自動釋放池定義的作用域內的其它對象可以向它發送消息。當程序執行到作用域結束的位置時,自動釋放池就會被釋放,池中的所有對象也就被釋放。
1.ojc-c是通過一種"referring counting"(引用計數)的方式來管理內存的,對象在開始分配內存(alloc)的時候引用計數為一,以后每當碰到有copy,retain的時候引用計數都會加一,每當碰到release和autorelease的時候引用計數就會減一,如果此對象的計數變為了0,系統才會調用dealloc真正銷毀這個對象.
2. NSAutoreleasePool就是用來做引用計數的管理工作的,這個東西一般不用你管的.
3. autorelease和release沒什么區別,只是引用計數減一的時機不同而已,autorelease會在對象的使用真正結束的時候才做引用計數減一.
22.類工廠方法是什么(就是便利構造器)
答案:類工廠方法的實現是為了向客戶提供方便,它們將分配和初始化合在一個步驟中,返回被創建的對象,并進行自動釋放處理。這些方法的形式是+ (type)className...(其中className不包括任何前綴)。
工廠方法可能不僅僅為了方便使用。它們不但可以將分配和初始化合在一起,還可以為初始化過程提供對象的分配信息。
類工廠方法的另一個目的是使類(比如NSWorkspace)提供單件實例。雖然init...方法可以確認一個類在每次程序運行過程只存在一個實例,但它需要首先分配一個“生的”實例,然后還必須釋放該實例。
工廠方法則可以避免為可能沒有用的對象盲目分配內存。
23.單件實例是什么
答案:Foundation和Application Kit框架中的一些類只允許創建單件對象,即這些類在當前進程中的唯一實例。舉例來說,NSFileManager和NSWorkspace類在使用時都是基于進程進行單件對象的實例化。當向這些類請求實例的時候,它們會向您傳遞單一實例的一個引用,如果該實例還不存在,則首先進行實例的分配和初始化。單件對象充當控制中心的角色,負責指引或協調類的各種服務。如果類在概念上只有一個實例(比如NSWorkspace),就應該產生一個單件實例,而不是多個實例;如果將來某一天可能有多個實例,您可以使用單件實例機制,而不是工廠方法或函數。
24.動態綁定
答案:動態綁定——在運行時確定要調用的方法。動態綁定將調用方法的確定也推遲到運行時。在編譯時,方法的調用并不和代碼綁定在一起,只有在消實發送出來之后,才確定被調用的代碼。通過動態類型和動態綁定技術,您的代碼每次執行都可以得到不同的結果。運行時因子負責確定消息的接收者和被調用的方法。運行時的消息分發機制為動態綁定提供支持。當您向一個動態類型確定了的對象發送消息時,運行環境系統會通過接收者的isa指針定位對象的類,并以此為起點確定被調用的方法,方法和消息是動態綁定的。而且,您不必在Objective-C代碼中做任何工作,就可以自動獲取動態綁定的好處。您在每次發送消息時,特別是當消息的接收者是動態類型已經確定的對象時,動態綁定就會例行而透明地發生。
25.obj-c的優缺點
答案:objc優點:1) Cateogies 2) Posing()3)動態識別4)指標計算5)彈性訊息傳遞6)不是一個過度復雜的C衍生語言7) Objective-C與C++可混合編程
缺點: 1)不支援命名空間2)不支持運算符重載3)不支持多重繼承4)使用動態運行時類型,所有的方法都是函數調用,所以很多編譯時優化方法都用不到。(如內聯函等),性能低劣。
26.sprintf,strcpy,memcpy使用上有什么要注意的地方
答案:strcpy是一個字符串拷貝的函數,它的函數原型為strcpy(char *dst,
const char *src);將src開始的一段字符串拷貝到dst開始的內存中去,結束的標志符號為'\0',由于拷貝的長度不是由我們自己控制的,所以這個字符串拷貝很容易出錯。
具備字符串拷貝功能的函數有memcpy,這是一個內存拷貝函數,它的函數原型為memcpy(char *dst, const
char* src, unsigned int len);將長度為len的一段內存,從src拷貝到dst中去,這個函數的長度可控。但是會有內存疊加的問題。
sprintf是格式化函數。將一段數據通過特定的格式,格式化到一個字符串緩沖區中去。sprintf格式化的函數的長度不可控,有可能格式化后的字符串會超出緩沖區的大小,造成溢出。
27.用變量a給出下面的定義
a)一個整型數(An integer)
b)一個指向整型數的指針(A pointer to an integer)
c)一個指向指針的的指針,它指向的指針是指向一個整型數(A pointer to a
pointer to an intege)r
d)一個有10個整型數的數組(An array of 10 integers)
e)一個有10個指針的數組,該指針是指向一個整型數的。(An array of 10
pointers to integers)
f)一個指向有10個整型數數組的指針(A pointer to an array of 10
integers)
g)一個指向函數的指針,該函數有一個整型參數并返回一個整型數(A pointer to afunction that takes an integer as an argumentand returns an integer)
h)一個有10個指針的數組,該指針指向一個函數,該函數有一個整型參數并返回一個整型數(An array of ten
pointers to functions t hat take an integer argument and return an integer)
答案:
a) int a; // An integer
b) int *a; // A pointer toan integer
c) int **a; // A pointer toa pointer to an integer
d) int a[10]; // An array of10 integers
e) int *a[10]; // An arrayof 10 pointers to integers
f) int (*a)[10]; // Apointer to an array of 10 integers
g) int (*a)(int); // A pointerto a function a thattakes an integerargument and returns an integer
h) int (*a[10])(int); // Anarray of 10 pointers to functionsthattake an integer argument and return an integer
28.cocoa有哪些設計模式?
答案:
29.socket編程中如何判斷異步connect是否成功
答案:創建一個socket,設為異步socket(fcntl),將socket加入epoll,connect到遠端(此時connect調用返回非0,但errno為EINPROGRESS,表示正在建立連接中)
epoll_wait之捕獲到EPOLLOUT事件,此時便認為connect已經成功,client端開始發消息
這個過程通常能夠運轉,但是線上環境復雜多變,如果發生這種情況:server進程調用listen開始偵聽后,被gdb或信號掛住了,此時異步connect會怎樣?很遺憾,client端的epoll_wait依然返回EPOLLOUT,甚至往此socket里發消息都返回成功,只有當發的消息多得占完了server端的tcp緩沖以后(窗口收縮到很小),send調用才開始失敗。這時候用losf -i看網絡連接也很有趣,client端的機器顯示連接建立了,server端的卻顯示沒有這個連接。
仔細想想,OS這樣做是正確的,畢竟connect的語義只是“連接”,當server掛住時,連接還是能成功的,但你能不能往里面發消息那就是另外一回事了。
所以對于應用來說,異步socket想要知道connect后連接是不是可以正常收發數據了,還是要靠應用層的一問一答才能知道。
30.[[[nil
retain]retain]release]有什么問題
答案:沒有問題
31.cocoa架構
答案:
32.readwrite,readonly,assign,retain,copy,nonatomic屬性的作用
答案:@property是 一個屬性訪問聲明,擴號內支持以下幾個屬性:
1.getter=getterName,setter=setterName,設置setter與getter的方法名
2.readwrite,readonly,設置可供訪問級別
3.assign,setter方法直接賦值,不進行 任何retain操作,為了解決原類型與環循引用問題
4.retain,setter方法對參數進行release舊值再retain新值,所有 實現都是這個順序(CC上有相關資料)
5.copy,setter方法進行Copy操作,與retain處理流程一樣,先舊值release,再Copy出新的對象,retainCount為1。這是為了減少對上下文的依賴而引入的機制。
6.nonatomic,非原子性訪問,不加同步,多線程并發訪問會提高性能。注意,如果不加此屬性,則默認是兩個訪問方法都為原子型事務訪問。鎖被加到所屬對象實例級(我是這么理解的...)。
二、(一共九題)
1.絡編程中設計并發服務器,使用多進程與多線程,請問有什么區別?
a)答1)進程:子進程是父進程的復制品。子進程獲得父進程數據空間、堆和棧的復制品。2)線程:相對與進程而言,線程是一個更加接近與執行體的概念,它可以與同進程的其他線程共享數據,但擁有自己的棧空間,擁有獨立的執行序列。
線程和進程在使用上各有優缺點:線程執行開銷小,但不利于資源管理和保護;而進程正相反。同時,線程適合于在SMP機器上運行,而進程則可以跨機器遷移。
2.數組a[N],存放了1至N-1個數,其中某個數重復一次。寫一個函數,找出被重復的數字.時間復雜度必須為o(N)函數原型:int do_dup(int a[],int N)
答:int do_dup(int a[],intN)
{
int sum= 0;
int sum2;
for(int i=0;i
{
Sum+=a[i];
}
Sum2 = (1+N-1)*N/2;
Return (sum-sum2);
}
3.一語句實現x是否為2的若干次冪的判斷
答:
方法1)int i = 512;
cout <<
boolalpha<< ((i & (i - 1)) ?false : true) << endl;//位與為0,則表示是2的若干次冪
方法2)return (x>>N==1);
4.unsigned int
intvert(unsigned int x,int p,intn)實現對x的進行轉換,p為起始轉化位,n為需要轉換的長度,假設起始點在右邊.如x=0b00010001,p=4,n=3轉換后x=0b0110 0001
答:unsigned int intvert(unsigned int x,int p,int n)//假定p=4,n=3
unsigned int _t = 0;unsignedint _a = 1;
for(int i = 0; i
++i)//循環的目的主要是-t_t |=_a;
_a = _a<<1;
_t =_t<
x ^=_t;
return x;
5.什么是預編譯,何時需要預編譯?
答:預編譯又稱為預處理,是做些代碼文本的替換工作。處理#開頭的指令,比如拷貝#include包含的文件代碼,#define宏定義的替換,條件編譯等,就是為編譯做的預備工作的階段,主要處理#開始的預編譯指令,預編譯指令指示了在程序正式編譯前就由編譯器進行的操作,可以放在程序中的任何位置。c編譯系統在對程序進行通常的編譯之前,先進行預處理。c提供的預處理功能主要有以下三種:1)宏定義2)文件包含3)條件編譯。
6.下述三個有什么區別?
char * const p;
char const * p
const char *p
char * const p; //常量指針,p的值不可以修改
char const * p;//指向常量的指針,指向的常量值不可以改
const char *p;//和char const *p
7.解釋下列輸出結果
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是指針,它們指向相同的常量區域。
8.以下代碼中的兩個sizeof用法有問題嗎?[C易]
void UpperCase( char str[] )
//將str中的小寫字母轉換成大寫字母
for( size_t i=0;i
if( 'a'<=str[i]&&str[i]<='z'str[i] -= ('a'-'A' );
char str[] ="aBcDe";
cout << "str字符長度為: "<
UpperCase( str );
cout << str<
答:函數內的sizeof有問題。根據語法,sizeof如用于數組,只能測出靜態數組的大小,無法檢測動態分配的或外部數組大小。函數外的str是一個靜態定義的數組,因此其大小為6,函數內的str實際只是一個指向字符串的指針,沒有任何額外的與數組相關的信息,因此sizeof作用于上只將其當指針看,一個指針為4個字節,因此返回4。
注意:數組名作為函數參數時,退化為指針.數組名作為sizeof()參數時,數組名不退化,因為sizeof不是函數.
三、(一共十六題)
1.objective-c中是所有對象間的交互是如何實現的?(深圳皆凱科技有限公司筆試題)
2.如何將產品進行多語言發布?
3.objective-c中是如何實現線程同步的?
4.編寫函數_memmove說明如下:實現C語言庫函數memmove的功能:將一塊緩沖區中的數據移動到另一塊緩沖區中。可能有重復。
5.什么叫數據結構?(面試順風快遞iPhone開發)
6.編程中,保存數據有哪幾種方式?
7.Sizeof與strlen的區別和聯系?
答案:
1.sizeof操作符的結果類型是size_t,它在頭文件中typedef為unsignedint類型。該類型保證能容納實現所建立的最大對象的字節大小。
2.sizeof是算符,strlen是函數。
3.sizeof可以用類型做參數,strlen只能用char*做參數,且必須是以''\0''結尾的。
4.數組做sizeof的參數不退化,傳遞給strlen就退化為指針了。
5.大部分編譯程序在編譯的時候就把sizeof計算過了是類型或是變量的長度這就是sizeof(x)可以用來定義數組維數的原因
char str[20]="0123456789";//str是編譯期大小已經固定的數組
int a=strlen(str); //a=10;//strlen()在運行起確定
int b=sizeof(str); //而b=20;//sizeof()在編譯期確定
6.strlen的結果要在運行的時候才能計算出來,是用來計算字符串的實際長度,不是類型占內存的大小。
7.sizeof后如果是類型必須加括弧,如果是變量名可以不加括弧。這是因為sizeof是個操作符不是個函數。
char c;
sizeof c;//變量名可以不加括弧
8.當適用了于一個結構類型時或變量,sizeof返回實際的大小,當適用一靜態地空間數組,sizeof歸還全部數組的尺寸。sizeof操作符不能返回動態地被分派了的數組或外部的數組的尺寸
9.數組作為參數傳給函數時傳的是指針而不是數組,傳遞的是數組的首地址,如:
fun(char [8])
fun(char [])
都等價于fun(char *)
在C++里參數傳遞數組永遠都是傳遞指向數組首元素的指針,編譯器不知道數組的大小
如果想在函數內知道數組的大小,需要這樣做:
進入函數后用memcpy拷貝出來,長度由另一個形參傳進去
fun(unsiged char *p1, int len)
{
unsigned char* buf = new unsigned char[len+1]
memcpy(buf, p1, len);
}
我們能常在用到sizeof和strlen的時候,通常是計算字符串數組的長度
看了上面的詳細解釋,發現兩者的使用還是有區別的,從這個例子可以看得很清楚:
har
str[11]="0123456789";//注意這里str大小因該大于等于11,應考慮'\0'在內,否則編譯器會報錯
int a=strlen(str); //a=10;
>>>> strlen計算字符串的長度,以結束符0x00為字符串結束。
int b=sizeof(str); //而b=11;
>>>> sizeof計算的則是分配的數組str[11]所占的內存空間的大小,不受里面存儲的內容改變。
上面是對靜態數組處理的結果,如果是對指針,結果就不一樣了
char* ss ="0123456789";
sizeof(ss)結果4===》ss是指向字符串常量的字符指針,sizeof獲得的是一個指針的之所占的空間,應該是長整型的,所以是4
sizeof(*ss)結果1===》*ss是第一個字符其實就是獲得了字符串的第一位'0'所占的內存空間,是char類型的,占了1位strlen(ss)= 10 >>>>如果要獲得這個字符串的長度,則一定要使用strlen另外,下面的方法可以用于確定該靜態數組可以容納元素的個數int a[3]={1,2,3};
cout << sizeof a/sizeof ( typeid( a[0] ).name() );
8.什么是抽象類?抽象類有什么作用?能實例化嗎?
9.用Objective-C寫冒泡法.
10.考察對@interface和@property的理解?
11.IPhone開發中控制類有什么作用?
12.線程中有哪些函數?寫出來。
13.有沒有寫過自定義的控件?
14.調用一個類的靜態方法需不需要release?
15.do-while與while-do的區別?
16.寫出幾個死循環?
答案:while(1){}
或者do{}while(1)
再或者for(;1;){}
還有goto的
Loop:
…
goto Loop;
四、(一共十八題)
1.ObjC中,與alloc語義相反的方法是dealloc還是release?與retain語義相反的方法是dealloc還是release,為什么?需要與alloc配對使用的方法是dealloc還是release,為什么?
答案::alloc與dealloc語意相反,alloc是創建變量,dealloc是釋放變量。retain對應release,retain保留一個對象。調用之后,變量的計數加1。或許不是很明顯,在這有例為證:
(void) setName : (NSString*)name {
[name retain];
[myname release];
myname = name;
}
我們來解釋一下:設想,用戶在調用這個函數的時候,他注意了內存的管理,所以他小心的寫了如下代碼:
NSString * newname =[[NSString alloc] initWithString: @"John"];
[aClass setName: newname];
[newname release];
我們來看一看newname的計數是怎么變化的。首先,它被alloc,count = 1;然后,在setName中,它被retain,count = 2;最后,用戶自己釋放newname,count = 1,myname指向了newname。這也解釋了為什么需要調用[myname release]。我們需要在給myname賦新值的時候,釋放掉以前老的變量。retain之后直接dealloc對象計數器沒有釋放。alloc需要與release配對使用,因為alloc這個函數調用之后,變量的計數加1。所以在調用alloc之后,一定要調用對應的release。另外,在release一個變量之后,他的值仍然有效,所以最好是后面緊接著再var = nil。
在一個對象的方法里面:
2.self.name =“object”;和name=”object”有什么不同嗎?
答案::self.name = "object"會調用對象的setName()方法,name = "object"會直接把object賦值給當前對象的name屬性。
[backcolor=transparent][backcolor=transparent]
3.這段代碼有什么問題嗎:
[backcolor=transparent]@implementationPerson
[backcolor=transparent]-(void)setAge:(int)newAge {
[backcolor=transparent]self.age= newAge;
[backcolor=transparent]}
[backcolor=transparent]@end
答案:會進入死循環。
4.什么是retain count?
答案::引用計數(ref count或者retain count)。對象的內部保存一個數字,表示被引用的次數。例如,某個對象被兩個指針所指向(引用)那么它的retain count為2。需要銷毀對象的時候,不直接調用dealloc,而是調用release。release會讓retain count減1,只有retain count等于0,系統才會調用dealloc真正銷毀這個對象。
5.以下每行代碼執行后,person對象的retain count分別是多少
Person *person = [[Personalloc] init]; count 1
[person retain]; count 2
[person release];count 1
[person release];retaincount = 1;
6.為什么很多內置類如UITableViewController的delegate屬性都是assign而不是retain的?
答案:會引起循環引用。
7.定義屬性時,什么情況使用copy,assign,和retain。
答案:assign用于簡單數據類型,如NSInteger,double,bool,retain和copy用戶對象,copy用于當a指向一個對象,b也想指向同樣的對象的時候,如果用assign,a如果釋放,再調用b會crash,如果用copy的方式,a和b各自有自己的內存,就可以解決這個問題。retain會使計數器加一,也可以解決assign的問題。另外:atomic和nonatomic用來決定編譯器生成的getter和setter是否為原子操作。在多線程環境下,原子操作是必要的,否則有可能引起錯誤的結果。加了atomic,setter函數會變成下面這樣:
if (property != newValue){[property release];property = [newValue retain];}
8.Autorelease的對象是在什么時候被release的?
答案:autorelease實際上只是把對release的調用延遲了,對于每一個Autorelease,系統只是把該Object放入了當前的Autorelease pool中,當該pool被釋放時,該pool中的所有Object會被調用Release。對于每一個Runloop,系統會隱式創建一個Autorelease pool,這樣所有的release pool會構成一個象CallStack一樣的一個棧式結構,在每一個Runloop結束時,當前棧頂的Autorelease pool會被銷毀,這樣這個pool里的每個Object(就是autorelease的對象)會被release。那什么是一個Runloop呢?一個UI事件,Timer call,delegate call,都會是一個新的Runloop。那什么是一個Runloop呢?一個UI事件,Timer call,delegate call,都會是一個新的Runloop。
9.這段代碼有什么問題,如何修改
for (int i = 0; i
{
NSString *string = @”Abc”;
string = [stringlowercaseString];
string = [stringstringByAppendingString:@"xyz"];
NSLog(@“%@”, string);
}答案::會內存泄露,
修改:
for(int i = 0; i<1000;i++){
NSAutoreleasePool * pool1 =[[NSAutoreleasePool alloc] init];
NSString *string =@"Abc";
string = [stringlowercaseString];
string = [stringstringByAppendingString:@"xyz"];
NSLog(@"%@",string);
[pool1 drain];
}
你的解決方法效率低,沒必要在每個循環都建立autorelease pool。在循環外面建一個就行了。
NSAutoreleasePool * pool1 =[[NSAutoreleasePool alloc] init];
for(int i = 0;i<1000;i++){
NSString *string =@"Abc";
string = [stringlowercaseString];
string = [stringstringByAppendingString:@"xyz"];
NSLog(@"%@",string);
}
[pool1 release];//[pool1
drain];效果相同,但我更喜歡release,看起來傳統一點
10.autorelease和垃圾回收機制(gc)有什么關系?答案::不懂
11.IPhone OS有沒有垃圾回收(gc)?沒有
12.什么是Notification?答案:觀察者模式,controller向defaultNotificationCenter添加自己的notification,其他類注冊這個notification就可以收到通知,這些類可以在收到通知時做自己的操作(多觀察者默認隨機順序發通知給觀察者們,而且每個觀察者都要等當前的某個觀察者的操作做完才能輪到他來操作,可以用NotificationQueue的方式安排觀察者的反應順序,也可以在添加觀察者中設定反映時間,取消觀察需要在viewDidUnload跟dealloc中都要注銷)。參考鏈接:http://useyourloaf.com/blog/2010/6/6/delegation-or-notification.html
13.什么時候用delegate,什么時候用Notification?答案:delegate針對one-to-one關系,并且reciever可以返回值給sender,notification可以針對one-to-one/many/none,reciever無法返回值給sender.所以,delegate用于sender希望接受到reciever的某個功能反饋值,notification用于通知多個object某個事件。
14.什么是KVC和KVO?答案:KVC(Key-Value-Coding)內部的實現:一個對象在調用setValue的時候,
(1)首先根據方法名找到運行方法的時候所需要的環境參數。
(2)他會從自己isa指針結合環境參數,找到具體的方法實現的接口。
(3)再直接查找得來的具體的方法實現。KVO(Key-Value-Observing):當觀察者為一個對象的屬性進行了注冊,被觀察對象的isa指針被修改的時候,isa指針就會指向一個中間類,而不是真實的類。所以isa指針其實不需要指向實例對象真實的類。所以我們的程序最好不要依賴于isa指針。在調用類的方法的時候,最好要明確對象實例的類名。
15.Notification和KVO有什么不同?答:不知道
16.KVO在ObjC中是怎么實現的?答:不知道
17.ViewController的loadView, viewDidLoad, viewDidUnload分別是在什么時候調用的?在自定義ViewController的時候這幾個函數里面應該做什么工作?
答案:viewDidLoad在view從nib文件初始化時調用,loadView在controller的view為nil時調用。此方法在編程實現view時調用,view控制器默認會注冊memory warning notification,當view controller的任何view沒有用的時候,viewDidUnload會被調用,在這里實現將retain的view release,如果是retain的IBOutlet view屬性則不要在這里release,IBOutlet會負責release。
18.ViewController的didReceiveMemoryWarning是在什么時候被調用的?默認的操作是什么?答案:默認調用[superdidReceiveMemoryWarning]
五、一共七題
1.Objective-C的內存管理方式, NSAutoreleasePool的作用
2.寫一個retain方式聲名屬性的setter方法
3.Objective-C與C的區別有哪些
4.列出你常用的幾個設計模式,列出如何在Objective-C中實現與應用
5.drawRect,
lasyoutSubViews的區別
6.列舉Cocoa中常用的幾種多線程實現,并談談多線程安全問題的幾種解決方案,什么地方會用到多線程
7.Socket連接相關庫,TCP,UDP的連接方法,HTTP的幾種常用方式
六、一共四題
1.用Objective-C寫冒泡法
2.Cocoa函數庫的使用
3.考察對線程的理解
4.考察對MVC的理解?模型—視圖—控制器
七、一共九題
1.Objective-C內部的實現
2.CALayer和View的關系
3.http協議,tcp/ip
4.UITableView的那些元素是可以自定義的?
5.c語言的,定義變量,比如int,在什么情況下,其最大值是不同的
6.比較32位平臺和64位平臺不同
7.iPhone app為什么會被打回來,如何避免??
8.為啥離開團隊?
八、一共十題
1.為什么很多內置類如UITableViewController的delegate屬性都是assign而不是retain?
會導致循環引用。
2.有如下一個類定義
interface MyClass : NSObject
{}
@property(retain) NSString *myProp;
@end
請完成myProp屬性的set方法:
-(void)setMyProp:(NSString*)aProp
{
if(myProp!=aPtrop)
[myProp release]
myProp=[aProp retain ]
}
3.寫出下面程序段的輸出結果
NSString *aStr = [[[NSString alloc]
initWithString:@”Hello World”] autoRelease];
NSMutableArray *aArray = [NSMutableArray array];
[aArray addObject:aStr];
NSLog(@”ref=%d”, [aStr retainCount])
4.簡述Notification的工作機制。
5.有一個UIView對象aView,當前大小為全屏。請編寫代碼實現如下效果:將aView的寬和高各縮小為原來一半,中心點仍在屏幕中心,并在縮小的同時實現漸隱。
6.寫出下面程序段的輸出結果
NSDictionary *dict = [NSDictionary dictionaryWithObject:@"a stringvalue" forKey:@"akey"];
NSLog(@"%@", [dict objectForKey:@"akey"]);
[dict release];
7.@class關鍵字有什么作用
8.不使用繼承,為NSStirng類添加新方法myPrint。
9.寫出下面程序段的輸出結果
NSArray array = [NSArrayarrayWithObjects:@"one",@"two",@"three",nil];
NSLog(@"%@", [array objectAtIndex:1]);
NSLog(@"%@", [array objectAtIndex:3]);