這家公司雖然是外包外派勺远,但是題目的水平啊不亞于大公司。
上題:
問答題
1 static 關(guān)鍵字的作用时鸵?
- static關(guān)鍵字修飾全局變量胶逢,該全局變量只能被該模塊內(nèi)的函數(shù)訪問,不能被模塊外的其他函數(shù)訪問饰潜;
- static關(guān)鍵字修飾局部變量初坠,該局部變量被分配到靜態(tài)存儲區(qū),內(nèi)存只被分配一次彭雾,所以下次訪該變量時碟刺,仍保持上次的值。
- static關(guān)鍵字修飾函數(shù)薯酝,該函數(shù)只能被該模塊內(nèi)的函數(shù)所調(diào)用半沽,對模塊外的其他函數(shù)是隱藏的。
- static關(guān)鍵字修飾類的成員變量吴菠,該變量屬于整個類所擁有者填,對所有類的對象只有一份拷貝;
- static關(guān)鍵字修飾類的成員函數(shù)做葵,該成員函數(shù)屬于整個類所擁有占哟,并且只能訪問static關(guān)鍵字修飾的成員變量。
2.OC的優(yōu)缺點(diǎn)酿矢?
OC的理解與特性
- OC作為一門面向?qū)ο蟮恼Z言榨乎,自然具有面向?qū)ο蟮恼Z言特性:封裝、繼承瘫筐、多態(tài)蜜暑。它既具有靜態(tài)語言的特性(如C++),又有動態(tài)語言的效率(動態(tài)綁定严肪、動態(tài)加載等)史煎。總體來講驳糯,OC確實(shí)是一門不錯的編程語言篇梭,
- Objective-C具有相當(dāng)多的動態(tài)特性,表現(xiàn)為三方面:動態(tài)類型(Dynamic typing)酝枢、動態(tài)綁定(Dynamic binding)和動態(tài)加載(Dynamic loading)恬偷。動態(tài)——必須到運(yùn)行時(run time)才會做的一些事情。
-
動態(tài)類型
:即運(yùn)行時再決定對象的類型帘睦,這種動態(tài)特性在日常的應(yīng)用中非常常見袍患,簡單來說就是id類型坦康。事實(shí)上,由于靜態(tài)類型的固定性和可預(yù)知性诡延,從而使用的更加廣泛滞欠。靜態(tài)類型是強(qiáng)類型,而動態(tài)類型屬于弱類型肆良,運(yùn)行時決定接受者筛璧。 -
動態(tài)綁定
:基于動態(tài)類型,在某個實(shí)例對象被確定后惹恃,其類型便被確定了夭谤,該對象對應(yīng)的屬性和響應(yīng)消息也被完全確定。 -
動態(tài)加載
:根據(jù)需求加載所需要的資源巫糙,最基本就是不同機(jī)型的適配朗儒,例如,在Retina設(shè)備上加載@2x的圖片参淹,而在老一些的普通蘋設(shè)備上加載原圖醉锄,讓程序在運(yùn)行時添加代碼模塊以及其他資源,用戶可根據(jù)需要加載一些可執(zhí)行代碼和資源承二,而不是在啟動時就加載所有組件榆鼠,可執(zhí)行代碼可以含有和程序運(yùn)行時整合的新類。
3 sprintf亥鸠, strcpy妆够,memcpy使用上有什么要注意的地方?
strcpy是一個字符串拷貝的函數(shù)负蚊,它的函數(shù)原型為strcpy(char *dst, c*****t char *src);
將 src開始的一段字符串拷貝到dst開始的內(nèi)存中去神妹,結(jié)束的標(biāo)志符號為'\0',由于拷貝的長度不是由我們自己控制的家妆,所以這個字符串拷貝很容易出錯鸵荠。具備字符串拷貝功能的函數(shù)有memcpy,這是一個內(nèi)存拷貝函數(shù)伤极,它的函數(shù)原型為memcpy(char dst, c*****t char src, unsigned int len);
將長度為len的一段內(nèi)存蛹找,從src拷貝到dst中去,這個函數(shù)的長度可控哨坪。但是會有內(nèi)存疊加的問題庸疾。
sprintf是格式化函數(shù)。將一段數(shù)據(jù)通過特定的格式当编,格式化到一個字符串緩沖區(qū)中去届慈。sprintf格式化的函數(shù)的長度不可控,有可能格式化后的字符串會超出緩沖區(qū)的大小,造成溢出金顿。
4 readwrite臊泌,readonly,assign揍拆,retain渠概,copy,nonatomic屬性的作用礁凡?
- readwrite 是可讀可寫特性高氮;需要生成getter方法和setter方法時(補(bǔ)充:默認(rèn)屬性,將生成不帶額外參數(shù)的getter和setter方法(setter方法只有一個參數(shù)))
- readonly 是只讀特性 只會生成getter方法 不會生成setter方法 ;不希望屬性在類外改變
- assign 是賦值特性顷牌,setter方法將傳入?yún)?shù)賦值給實(shí)例變量;僅設(shè)置變量時塞淹;
- retain 表示持有特性窟蓝,setter方法將傳入?yún)?shù)先保留,再賦值饱普,傳入?yún)?shù)的retaincount會+1;
- copy 表示拷貝特性运挫,setter方法將傳入對象復(fù)制一份;需要完全一份新的變量時套耕。
- nonatomic 非原子操作谁帕,決定編譯器生成的setter getter是否是原子操作,atomic表示多線程安全冯袍,一般使用nonatomic匈挖。
5 什么時候用delegate,什么時候通知康愤?
區(qū)別
-NotificationCenter 通知中心
:“一對多”儡循,在APP中,很多控制器都需要知道一個事件征冷,應(yīng)該用通知择膝;
-delegate 代理委托
:
1.“一對一”,對同一個協(xié)議检激,一個對象只能設(shè)置一個代理delegate肴捉,所以單例對象就不能用代理;
2.代理更注重過程信息的傳輸:比如發(fā)起一個網(wǎng)絡(luò)請求叔收,可能想要知道此時請求是否已經(jīng)開始齿穗、是否收到了數(shù)據(jù)、數(shù)據(jù)是否已經(jīng)接受完成今穿、數(shù)據(jù)接收失敗缤灵。
6 frame和bounds有什么不同?
- frame指的是:該view在父view坐標(biāo)系統(tǒng)中的位置和大小。(參照點(diǎn)是父親的坐標(biāo)系統(tǒng))
- bounds指的是:該view在本身坐標(biāo)系統(tǒng)中的位置和大小腮出。(參照點(diǎn)是本身坐標(biāo)系統(tǒng))
7 是否可以在一個視圖控制器里嵌入兩個tableView控制器帖鸦?
- 如果是視圖的話,一個視圖下當(dāng)然可以有兩個tableView胚嘲。
- 如果是控制器的話作儿,tabBarController下就可以有多個控制器。
8 堆棧溢出一般是什么原因?qū)е碌模?/h3>
堆和棧的區(qū)別
- 棧區(qū)(stack)由編譯器自動分配釋放 ,存放方法(函數(shù))的參數(shù)值, 局部變量的值等馋劈,棧是向低地址擴(kuò)展的數(shù)據(jù)結(jié)構(gòu)攻锰,是一塊連續(xù)的內(nèi)存的區(qū)域。即棧頂?shù)牡刂泛蜅5淖畲笕萘渴窍到y(tǒng)預(yù)先規(guī)定好的妓雾。
- 堆區(qū)(heap)一般由程序員分配釋放, 若程序員不釋放,程序結(jié)束時由OS回收娶吞,向高地址擴(kuò)展的數(shù)據(jù)結(jié)構(gòu),是不連續(xù)的內(nèi)存區(qū)域械姻,從而堆獲得的空間比較靈活妒蛇。
- 碎片問題:對于堆來講,頻繁的new/delete勢必會造成內(nèi)存空間的不連續(xù)楷拳,從而造成大量的碎片绣夺,使程序效率降低。對于棧來講欢揖,則不會存在這個問題陶耍,因?yàn)闂J窍冗M(jìn)后出的隊(duì)列,他們是如此的一一對應(yīng)她混,以至于永遠(yuǎn)都不可能有一個內(nèi)存塊從棧中間彈出.
- 分配方式:堆都是動態(tài)分配的烈钞,沒有靜態(tài)分配的堆。棧有2種分配方式:靜態(tài)分配和動態(tài)分配产上。靜態(tài)分配是編譯器完成的棵磷,比如局部變量的分配。動態(tài)分配由alloca函數(shù)進(jìn)行分配晋涣,但是棧的動態(tài)分配和堆是不同的仪媒,他的動態(tài)分配是由編譯器進(jìn)行釋放,無需我們手工實(shí)現(xiàn)谢鹊。
- 分配效率:棧是機(jī)器系統(tǒng)提供的數(shù)據(jù)結(jié)構(gòu)算吩,計(jì)算機(jī)會在底層對棧提供支持:分配專門的寄存器存放棧的地址,壓棧出棧都有專門的指令執(zhí)行佃扼,這就決定了棧的效率比較高偎巢。堆則是C/C++函數(shù)庫提供的,它的機(jī)制是很復(fù)雜的兼耀。
- 全局區(qū)(靜態(tài)區(qū))(static),全局變量和靜態(tài)變量的存儲是放在一塊 的,初始化的全局變量和靜態(tài)變量在一塊區(qū)域, 未初始化的全局變量和未初始化的靜態(tài)變量在相鄰的另一塊區(qū)域压昼。程序結(jié)束后有系統(tǒng)釋放求冷。
- 文字常量區(qū)—常量字符串就是放在這里的。程序結(jié)束后由系統(tǒng)釋放窍霞。
- 程序代碼區(qū)—存放函數(shù)體的二進(jìn)制代碼
詳細(xì)知識請移步堆棧的深入個人理解
9 什么函數(shù)不能聲明虛函數(shù)匠题?(C++內(nèi)容都有)
** 一.首先回顧下什么是虛函數(shù)及其作用,以便更好理解什么函數(shù)不 能聲明或定義為虛函數(shù)**:
- 定義:
虛函數(shù)必須是基類的非靜態(tài)成員函數(shù)但金,其訪問權(quán)限可以是protected或public韭山,在基類的類定義中定義虛函數(shù)的一般形式:
virtual 函數(shù)返回值類型 虛函數(shù)名(形參表) { 函數(shù)體 }
- 作用:
虛函數(shù)的作用是實(shí)現(xiàn)動態(tài)聯(lián)編,也就是在程序的運(yùn)行階段動態(tài)地選擇合適的成員函數(shù)冷溃,在定義了虛函數(shù)后钱磅,可以在基類的派生類中對虛函數(shù)重新定義,在派生類中重新定義的函數(shù)應(yīng)與虛函數(shù)具有相同的形參個數(shù)和形參類型似枕,以實(shí)現(xiàn)統(tǒng)一的接口盖淡,不同定義過程。如果在派生類中沒有對虛函數(shù)重新定義菠净,則它繼承其基類的虛函數(shù)禁舷。
當(dāng)程序發(fā)現(xiàn)虛函數(shù)名前的關(guān)鍵字virtual后,會自動將其作為動態(tài)聯(lián)編處理毅往,即在程序運(yùn)行時動態(tài)地選擇合適的成員函數(shù)。 - 使用方法:
動態(tài)聯(lián)編規(guī)定派近,只能通過指向基類的指針或基類對象的引用來調(diào)用虛函數(shù)攀唯,其格式:
指向基類的指針變量名->虛函數(shù)名(實(shí)參表)
或
基類對象的引用名. 虛函數(shù)名(實(shí)參表)
- 其它說明:
虛函數(shù)是C++多態(tài)的一種表現(xiàn):
例如:子類繼承了父類的一個函數(shù)(方法),而我們把父類的指針指向子類渴丸,則必須把父類的該函數(shù)(方法)設(shè)為virtual(虛函數(shù))侯嘀。 使用虛函數(shù)谱轨,我們可以靈活的進(jìn)行動態(tài)綁定戒幔,當(dāng)然是以一定的開銷為代價。 如果父類的函數(shù)(方法)根本沒有必要或者無法實(shí)現(xiàn)土童,完全要依賴子類去實(shí)現(xiàn)的話诗茎,可以把此函數(shù)(方法)設(shè)為virtual 函數(shù)名=0 我們把這樣的函數(shù)(方法)稱為純虛函數(shù)∠缀梗 如果一個類包含了純虛函數(shù)敢订,稱此類為抽象類 。
二罢吃、什么函數(shù)不能聲明為虛函數(shù):
一個類中將所有的成員函數(shù)都盡可能地設(shè)置為虛函數(shù)總是有益的楚午。
設(shè)置虛函數(shù)須注意:
1.只有類的成員函數(shù)才能說明為虛函數(shù);
2.靜態(tài)成員函數(shù)不能是虛函數(shù)尿招;
3.內(nèi)聯(lián)函數(shù)不能為虛函數(shù)矾柜;
4.構(gòu)造函數(shù)不能是虛函數(shù)阱驾;
5.析構(gòu)函數(shù)可以是虛函數(shù),而且通常聲明為虛函數(shù)怪蔑。
類里面“定義”的成員函數(shù)是內(nèi)聯(lián)的里覆,但是仍然可以成為虛函數(shù),那么是不是可以說“內(nèi)聯(lián)函數(shù)不能成為虛函數(shù)”這句話有問題呢饮睬,是不是應(yīng)該改成“顯式定義的內(nèi)聯(lián)函數(shù)不能成為虛函數(shù)”租谈。比如下面這個示例程序:
#include <iostream>
using namespace std;
class Base{
public:
virtual void f1(){cout < < "Father " < <endl;}
};
class Drived1:public Base{
public:
void f1(){cout < < "Son1 " < <endl;}
};
class Drived2:public Base{
public:
void f1(){cout < < "Son2 " < <endl;}
};
void myPrint(Base* pBs){
pBs-> f1();
}
int main() {
Base father;
Drived1 son1;
Drived2 son2;
myPrint(&father);
myPrint(&son1);
myPrint(&son2);
system( "PAUSE ");
return 0;
}
輸出:
Father
Son1
Son2
10 冒泡排序的時間復(fù)雜度是什么?
上代碼:
int a[7] = {10,8,5,27,7,11,90};
int z = 0;
for (int i =0; i < 7-1; i++) {
for(int j =0; j < 7 - 1 - i; j++) {
if (a[j] > a[j +1]) {
z = a[j];
a[j] = a[j +1];
a[j +1] = z;
}
}
}
for(inti =0;i <7;i++){
printf("%d ",a[i]);
}
這不就是O(n^2)嗎
11 寫出float x與“零值”比較的if語句捆愁?
const float EPSINON = 0.00001;
if ((x >= - EPSINON) && (x <= EPSINON)
- 不可將浮點(diǎn)變量用“==”或“割去!=”與數(shù)字比較,應(yīng)該設(shè)法轉(zhuǎn)化成“>=”或“<=”此類形式昼丑。
- EPSINON應(yīng)該是一個很小的值吧 因?yàn)橛?jì)算機(jī)在處理浮點(diǎn)數(shù)的時候是有誤差的呻逆,所以判斷兩個浮點(diǎn)數(shù)是不是相同,是要判斷是不是落在同一個區(qū)間的菩帝,這個區(qū)間就是 [-EPSINON,EPSINON] EPSINON一般很小咖城,10的-6次方以下吧,具體的好像不確定的呼奢,和機(jī)器有關(guān)宜雀。
12 全局變量可不可以定義在可被多個.C文件包含的頭文件里?為什么握础?(C++)
有是C++的題目辐董,真是一臉懵啊禀综!
詳細(xì)請移步[C/C++]在頭文件中使用static定義變量意味著什么
13 do......while和while........do有什么區(qū)別简烘?
那就寫代碼才可以看出來:
do...while語句:
while語句:
- 與上面的do語句不同,while語句會在開始的時候判斷控制表達(dá)式的值(do語句則在執(zhí)行完一次循環(huán)體內(nèi)再判斷控制表達(dá)式的值)定枷。do語句一定會執(zhí)行一次循環(huán)體中的語句孤澎,而while語句并不一定會執(zhí)行循環(huán)體內(nèi)的語句。如果控制表達(dá)式的第一次判斷結(jié)果為0欠窒,則循環(huán)體中的語句一次也不會執(zhí)行覆旭。
所以:
找錯題##
試題1:
void test1()
{
char string[10];
char *str1 = "0123456789";
strcpy(string, str1);
}
類型不一樣無法拼接
試題2:
void test2()
{
char string[10], str1;
int i;
for (i = 10; i < 10; i++) {
str1 = 'a';
}
strcpy(string, str1);
}
試題3:
void test3(char *str1)
{
char string[10];
if (strlen(str1) < = 10) {
strcpy(string, str1);
}
}
計(jì)算題##
以下為window NT下的32位C++程序,請計(jì)算sizeof的值
void Func(char str[100])
{
sizeof(str) = ?
}
void *p = malloc(100);
sizeof(p) = ?
填空題##
編寫一個函數(shù)贱迟,作用是把一個char組成的字符串循環(huán)右移n個姐扮。比如“abcdefghi”,如果n = 2衣吠,移動后應(yīng)該為“hiabcdefgh”####
函數(shù)頭應(yīng)該是這樣的:
//pStr是指向以‘\0’結(jié)尾字符串的指針
//steps是要求移動的n
void LoopMove(char *pStr茶敏, int step)
{
//請補(bǔ)充。缚俏。惊搏。贮乳。
}