iosc語言函數
㈠ 借用C語言中堆和棧的區別來說明IOS中兩者的
一、預備知識—程序的內存分配
一個由C/C++編譯的程序佔用的內存分為以下幾個部分
1、棧區(stack)— 由編譯器自動分配釋放 ,存放函數的參數值,局部變數的值等。其
操作方式類似於數據結構中的棧。 (補充:局部變數, 生命周期外自動被系統回收)
2、堆區(heap) — 一般由程序員分配釋放, 若程序員不釋放,程序結束時可能由OS回
收 。注意它與數據結構中的堆是兩回事,分配方式倒是類似於鏈表,呵呵。 (補充:malloc、alloc出的空間,必須手動釋放)
3、全局區(靜態區)(static)—,全局變數和靜態變數的存儲是放在一塊的,初始化的
全局變數和靜態變數在一塊區域, 未初始化的全局變數和未初始化的靜態變數在相鄰的另
一塊區域。 - 程序結束後由系統釋放。 (補充:static 關鍵字修飾的變數 該區上的數據在應用程序的整個生命周期中一直存在 只有當程序退出時才會被系統回收)
4、文字常量區 —常量字元串就是放在這里的。 程序結束後由系統釋放
5、程序代碼區—存放函數體的二進制代碼。
//半路插入IOS中的理解
操作系統iOS中應用程序使用的計算機內存不是統一分配空間,運行代碼使用的空間在三個不同的內存區域,分成三個段:「text segment「,「stack segment」,「heap segment」。
段「text segment」是應用程序運行時應用程序代碼存在的內存段。每一個指令,每一個單個函數、過程、方法和執行代碼都存在這個內存段中直到應用程序退出。一般情況下,你不會真的不得不知道這個段的任何事情。
當應用開始以後,函數main()被調用,一些空間分配在」stack」中。這是為應用分配的另一個段的內存空間,這是為了函數變數存儲需要而分配的內存。每一次在應用中調用一個函數,「stack」的一部分會被分配在」stack」中,稱之為」frame」。新函數的本地變數分配在這里。
正如名稱所示,「stack」是後進先出(LIFO)結構。當函數調用其他的函數時,「stack frame」會被創建;當其他函數退出後,這個「frame」會自動被破壞。
「heap」段也稱為」data」段,提供一個保存中介貫穿函數的執行過程,全局和靜態變數保存在「heap」中,直到應用退出。
為了訪問你創建在heap中的數據,你最少要求有一個保存在stack中的指針,因為你的CPU通過stack中的指針訪問heap中的數據。
你可以認為stack中的一個指針僅僅是一個整型變數,保存了heap中特定內存地址的數據。實際上,它有一點點復雜,但這是它的基本結構。
簡而言之,操作系統使用stack段中的指針值訪問heap段中的對象。如果stack對象的指針沒有了,則heap中的對象就不能訪問。這也是內存泄露的原因。
在iOS操作系統的stack段和heap段中,你都可以創建數據對象。
stack對象的優點主要有兩點,一是創建速度快,二是管理簡單,它有嚴格的生命周期。stack對象的缺點是它不靈活。創建時長度是多大就一直是多大,創建時是哪個函數創建的,它的owner就一直是它。不像heap對象那樣有多個owner,其實多個owner等同於引用計數。只有heap對象才是採用「引用計數」方法管理它。
stack對象的創建
只要棧的剩餘空間大於stack對象申請創建的空間,操作系統就會為程序提供這段內存空間,否則將報異常提示棧溢出。
heap對象的創建
操作系統對於內存heap段是採用鏈表進行管理的。操作系統有一個記錄空閑內存地址的鏈表,當收到程序的申請時,會遍歷鏈表,尋找第一個空間大於所申請的heap節點,然後將該節點從空閑節點鏈表中刪除,並將該節點的空間分配給程序。
例如:
NSString的對象就是stack中的對象,NSMutableString的對象就是heap中的對象。前者創建時分配的內存長度固定且不可修改;後者是分配內存長度是可變的,可有多個owner,適用於計數管理內存管理模式。
兩類對象的創建方法也不同,前者直接創建「NSString * str1=@"welcome";「,而後者需要先分配再初始化「NSMutableString * mstr1=[[NSMutableString alloc] initWithString:@"welcome"];」。
再補充一點,這里說的是操作系統的堆和棧。
在我們學習「數據結構」時,接觸到的堆和棧的概念和這個操作系統中的堆和棧不是一回事的。
操作系統的堆和棧是指對內存進行操作和管理的一些方式。
「數據結構「的堆實際上指的就是(滿足堆性質的)優先Queue的一種數據結構,第1個元素有最高的優先權;棧實際上就是滿足先進後出的性質的數據或數據結構。
//插入結束
二、例子程序
這是一個前輩寫的,非常詳細
//main.cpp
int a = 0; 全局初始化區
char *p1; 全局未初始化區
main()
{
int b; 棧
char s[] = "abc"; 棧
char *p2; 棧
char *p3 = "123456"; 123456/0在常量區,p3在棧上。
static int c =0; 全局(靜態)初始化區
p1 = (char *)malloc(10);
p2 = (char *)malloc(20);
分配得來得10和20位元組的區域就在堆區。
strcpy(p1, "123456"); 123456/0放在常量區,編譯器可能會將它與p3所指向的"123456"
優化成一個地方。
}
二、堆和棧的理論知識
2.1申請方式
stack:
由系統自動分配。 例如,聲明在函數中一個局部變數 int b; 系統自動在棧中為b開辟空
間
heap:
需要程序員自己申請,並指明大小,在c中malloc函數
如p1 = (char *)malloc(10);
在C++中用new運算符
如p2 = new char[10];
但是注意p1、p2本身是在棧中的。
2.2
申請後系統的響應
棧:只要棧的剩餘空間大於所申請空間,系統將為程序提供內存,否則將報異常提示棧溢
出。
堆:首先應該知道操作系統有一個記錄空閑內存地址的鏈表,當系統收到程序的申請時,
會遍歷該鏈表,尋找第一個空間大於所申請空間的堆結點,然後將該結點從空閑結點鏈表
中刪除,並將該結點的空間分配給程序,另外,對於大多數系統,會在這塊內存空間中的
首地址處記錄本次分配的大小,這樣,代碼中的delete語句才能正確的釋放本內存空間。
另外,由於找到的堆結點的大小不一定正好等於申請的大小,系統會自動的將多餘的那部
分重新放入空閑鏈表中。
2.3申請大小的限制
棧:在Windows下,棧是向低地址擴展的數據結構,是一塊連續的內存的區域。這句話的意
思是棧頂的地址和棧的最大容量是系統預先規定好的,在WINDOWS下,棧的大小是2M(也有
的說是1M,總之是一個編譯時就確定的常數),如果申請的空間超過棧的剩餘空間時,將
提示overflow。因此,能從棧獲得的空間較小。
堆:堆是向高地址擴展的數據結構,是不連續的內存區域。這是由於系統是用鏈表來存儲
的空閑內存地址的,自然是不連續的,而鏈表的遍歷方向是由低地址向高地址。堆的大小
受限於計算機系統中有效的虛擬內存。由此可見,堆獲得的空間比較靈活,也比較大。2.4申請效率的比較:
棧由系統自動分配,速度較快。但程序員是無法控制的。
堆是由new分配的內存,一般速度比較慢,而且容易產生內存碎片,不過用起來最方便.
另外,在WINDOWS下,最好的方式是用VirtualAlloc分配內存,他不是在堆,也不是在棧是
直接在進程的地址空間中保留一塊內存,雖然用起來最不方便。但是速度快,也最靈活。
2.5堆和棧中的存儲內容
棧: 在函數調用時,第一個進棧的是主函數中後的下一條指令(函數調用語句的下一條可
執行語句)的地址,然後是函數的各個參數,在大多數的C編譯器中,參數是由右往左入棧
的,然後是函數中的局部變數。注意靜態變數是不入棧的。
當本次函數調用結束後,局部變數先出棧,然後是參數,最後棧頂指針指向最開始存的地
址,也就是主函數中的下一條指令,程序由該點繼續運行。
堆:一般是在堆的頭部用一個位元組存放堆的大小。堆中的具體內容由程序員安排。
2.6存取效率的比較
char s1[] = "aaaaaaaaaaaaaaa";
char *s2 = "bbbbbbbbbbbbbbbbb";
aaaaaaaaaaa是在運行時刻賦值的;
而bbbbbbbbbbb是在編譯時就確定的;
但是,在以後的存取中,在棧上的數組比指針所指向的字元串(例如堆)快。
比如:
#include
void main()
{
char a = 1;
char c[] = "1234567890";
char *p ="1234567890";
a = c[1];
a = p[1];
return;
}
對應的匯編代碼
10: a = c[1];
00401067 8A 4D F1 mov cl,byte ptr [ebp-0Fh]
0040106A 88 4D FC mov byte ptr [ebp-4],cl
11: a = p[1];
0040106D 8B 55 EC mov edx,dword ptr [ebp-14h]
00401070 8A 42 01 mov al,byte ptr [edx+1]
00401073 88 45 FC mov byte ptr [ebp-4],al
第一種在讀取時直接就把字元串中的元素讀到寄存器cl中,而第二種則要先把指針值讀到
edx中,再根據edx讀取字元,顯然慢了。
2.7小結:
堆和棧的區別可以用如下的比喻來看出:
使用棧就象我們去飯館里吃飯,只管點菜(發出申請)、付錢、和吃(使用),吃飽了就
走,不必理會切菜、洗菜等准備工作和洗碗、刷鍋等掃尾工作,他的好處是快捷,但是自
由度小。
使用堆就象是自己動手做喜歡吃的菜餚,比較麻煩,但是比較符合自己的口味,而且自由
度大。 (經典!)
㈡ C語言isxdigit函數問題
我隨便寫了個程序測試了下這個函數
#include<ctype.h>
#include<iostream>
#include<fstream>
usingnamespacestd;
intmain()
{
ofstreamfile("test.txt",ios::out);
for(inti=0;i<256;i++)
file<<i<<" "<<(char)i<<" "<<isxdigit(i)<<" ";
file.close();
return0;
然後輸出的結果是這樣的
大致分析這個函數是這個意思:
當某個輸入的char型數據的ascii碼是0-9或a-f或A-f時函數返回128否則返回0