IOS基礎學習之C(一)

iOS開發的核心語言是Objective-C,Objective-C是在C語言的基礎加了一層面向對象的語法。爲了能夠更好地掌握Objective-C,我們可以先學習C語言,然後在C語言的基礎上升華到Objective-C。

C語言:
是編譯型語言;
*C語言於1972年發明,首次使用是用於重寫UINX操作系統(UNIX以前是用匯編寫的)
*C語言是一門面向過程的語言,非面向對象的語言
++ 特點:
*弱語法;
*提供了34種運算符;
*有豐富的數據類型;整型(int)、float、char、int[]、指針類型(void *)、結構體類型(struct)、共用體類型(union)等;
*允許直接訪問物理地址,對硬件進行操作;最強大的是指針,可通過指針直接訪問內存地址,使用得當,可節省代碼量,優化內存管理、提高性能;
*具有高級語言的功能,又具有低級語言的許多功能能如彙編語言一樣對位(bit)、字節和地址進行操作(這三者是計算機工作的基本單元);
*高效率的目標代碼;可讀性好,易於調試,修改和移植,代碼質量與彙編相當;
*可移植性好;在一個環境上用C語言編寫的程序,不改動或稍加改動,就可移植到另一個完全不同的環境中;

**不足:
*由於C語言是面向過程的,因此它的數據封裝性差、安全性低,這就是C語言和其他面嚮對象語言的區別之一。面嚮對象語言的特性之一就是數據的封裝性;
*語法限制不嚴格,對變量的類型約束不嚴格,對數組下標越界不作檢查等;
+使用:
*由於C語言具有強大的數據處理能力,而且允許直接訪問物理地址,直接對硬件操作,因此它適於編寫系統軟件、圖形處理、單片機程序、嵌入式系統開發甚至是用於科研;
* 很多操作系統的底層都是用C語言寫的,比如android;
*iOS開發中的核心語言是Objective-C(簡稱OC),OC是在C語言的基礎上加了一層面向對象語法;
+標準:1983年美國國家標準局(American National Standards Institute,簡稱ANSI)成立了一個委員會,開始制定C語言標準的工作。1989年C語言標準被批准,這個版本的C語言標準通常被稱爲ANSI C;
— Xcode中的C語言是在標準的C 語言上做了一些封裝;
+語法:
[goto語句一般很少使用,會破壞程序的結構;佔位符同android string;%f 默認6位小數;]

blob9.png

函數(方法):
以#開頭爲預處理指令;在編譯之前執行的指令;include的作用只是把後面<**>中的內容拷貝到該處;
若導入的文件是系統自帶的文件用<>,自己寫的文件用””;
.h稱爲頭文件;用來聲明一些常用的函數;若想使用這些函數,就必須包含這個頭文件;函數具體的實現是放在其他文件的;
一個C程序只有一個入口main函數;
面向過程:就是先分析出解決問題所需要的步驟,然後用函數把這些步驟一步一步實現,使用的時候一個一個依次調用函數就可以了;(只寫函數,不使用對象)
一個C程序中一定會有一個main函數,也只能有一個main函數。main函數是整個C程序的入口。main.c的第3行代碼就定義了一個main函數。
main函數的返回值爲int類型,接收2個參數,其實可以不寫參數;
main函數沒有寫返回值類型,並不代表函數沒有返回值,而是表示返回值類型爲int類型,void才代表函數沒有返回值;可直接寫main(){…}

+運行過程:
blob10.png

目標代碼須和C 語言的函數庫鏈接在一起,找個頭文件中的引用的函數名的實現生成的機器代碼才能運行。

+1+ 編寫程序

C語言源文件的擴展名爲”.c”,源文件以ASCII碼形式存儲,不能直接被計算機執行;
+2+ 編譯(VC)[main.c—>main.obj]
1)把C的源程序翻譯成計算機可以識別的二進制形式的目標代碼文件,這個過程稱爲編譯,由C的編譯器完成
2)在編譯的同時,還對源程序的語法等進行檢查。若出現語法錯誤,則編譯失敗。如果編譯成功則生成目標文件,目標文件名跟源程序文件名一樣,擴展名爲”.obj”。比如,mj.c編譯後生成目標文件mj.obj
3)每個源文件是單獨進行編譯的,假如一個項目中有多個.c源文件,編譯成功會生成多個對應的.obj目標。一般情況下,目標文件之間是有關聯的,比如 a.obj 可能會調用 b.obj 中定義的一個函數,因此它們都不能夠單獨被計算機執行,而且目標文件中並不包含程序運行所需要的庫函數等
頭文件不會被編譯;
+3+ 鏈接(VC下)
將所有有關聯的obj目標文件,以及系統提供的C庫函數等組合在一起生成可執行文件的過程,稱爲”鏈接”
鏈接生成的可執行文件的文件名跟源程序文件同名,(win下)擴展名爲”.exe”,計算機可以直接執行;
+4+ 運行
win下的.exe;Mac下爲exec,雙擊即可執行;

函數:
主函數:main;有且只有一個;不論什麼位置,都是從main 開始執行;
自定義函數:
C庫提供的庫函數;
++ 聲明與定義:
在標準C語言中,是從上向下編譯,故只有後面的函數才能調用前面定義過的函數;
[在使用中可將函數名在mian()方法前聲明,在項目開發中,爲了分模塊開發,一般會將函數的聲明和定義(實現)分別放在2個文件中,函數聲明放在.h頭文件中,函數定義放在.c源文件中;這樣使項目結構清晰。]
(由於include只是拷貝,可直接include “header.c”;但不能重複導入頭文件,故一般不這樣寫;””的方式是先在當前源程序下找,若找不到,再到系統的path中找;<>是隻在c語言庫函數文件中找)
—-[函數在整個項目中不允許重複定義,不支持重載]—-
形參和實參:若是基本數據類型作爲函數的形參,那就是簡單的傳遞,將實參賦值給了形參b;和b是分別有着不同內存地址的2個變量,因此改變了形參b的值,並不會影響實參a的值。

— printf():
佔位符:
%d 整型,%4d表示佔用4個位置空間;
%s String
%c char 只能表示一個字符,但一箇中文至少佔用兩個字符;
%f 浮點數;%.2f表示保留兩位小數;默認六位小數;
%o 以不帶符號的八進制輸出
%x 以不帶符號的十六進制輸出
%e 以標準指數形式輸出單、雙精度數,數字部分小數位爲6位

  • scanf
    阻塞式函數,不輸入不向下執行;
    要對變量進行賦值,須使用地址和佔位符;如:int a;scanf(“%d”,&a);
    &a表示變量a的地址;
    scanf(“%d-%d”,&a,&b);則輸入也須是a-b的形式;

  • 數據類型
    blob11.png
    結構體,類似class ;共用體很少使用;
    int 整型 2個字節;
    float 單精度浮點型 4個字節
    double 雙精度浮點型 8個字節
    char 字符型 1個字節,同java,只能存儲一個字符(不能是中文,同java);
    變量:若未初始化會自動賦值(全局變量會爲0(int),但局部變量可能是一個隨機數,必須初始化後再使用,更安全);
    類型修飾符:
    short 短型;short int =1;限制取值範圍;
    long 長型;擴展int的取值範圍;long a=1;等同於 long int a=1;(C中無long型,long只是一個修飾符)
    signed 有符號型;signed int a=1;等同於int a=1;可爲正數也可爲負;
    unsigned 無符號型;只能爲正數或0;
    可同時使用 unsigned long int a=5;
    [不同的編譯器,取值範圍不同;]
    基本語句(同java)
    基本運算(同java)
    但由於C沒有boolean故沒有true和false;用1和0來表示true和false;
    如:5>4 —> 1; 5<4 —>0;
    ** 在if語句中,所有非0(包括負數)的值都爲真(true)
    [NOTE:像a==0這樣的表達式,最好寫成0==a。因爲若誤寫成0=a,編譯器會直接報錯,而a=0是不會報錯的。]
    ** 在C中,可以不保存關係去處的結果;如:a>10;a==0;
    ** && 與 || 同Java 也是阻斷式的;
    +逗號表達式;
    返回值爲最後一個表達式的值;如:
    int e=2,f=4;
    int g = (++e,e*f); g—>12; 若int g = ++e,e*f;則相當於g=(++e),值爲3;

+sizeof
用於得到數據佔用的字節長度,返回值爲size_t(即unsigned long,可直接使用int);使用 size_t size=sizeof(a);

  • 地址
  • 計算機中的內存是以字節爲單位的存儲空間。內存的每一個字節都有一個唯一的編號,這個編號就稱爲地址。
    *凡存放在內存中的程序和數據都有一個地址,也就是說,一個函數也有自己的內存地址。
    *當定義一個變量時,系統就分配一個帶有唯一地址的存儲單元來存儲這個變量。變量存儲單元的第一個字節的地址就是該變量的地址。
    *獲取地址: &a;
    +數組
    只能是int a[5];的形式(int[5] a;int[] b;int a[];int i=0;int a[i]均錯誤。int)

[]裏面的個數必須是一個固定值,可以是常量(比如6、8)、常量表達式(比如3+4、5*7)。絕對不能使用變量或者變量表達式來表示元素個數,大多數情況下不要省略元素個數(當數組作爲函數的形參和數組初始化時除外)

*一維數組
定義數組時,系統將按照數組類型和個數分配一段連續的存儲空間來存儲數組元素,如int a[3]佔據了連續的6字節存儲空間(在16位編譯器環境下,一個int類型佔用2個字節)。要注意的是,數組名代表着整個數組的地址,也就是數組的起始地址。
其實a不算是變量,是個常量,它代表着數組的地址,不能對其賦值[int a[2];a={1,2};//是錯誤的]。]
數組a的地址是ffc1,a[0]的地址是ffc1,a[1]的地址是ffc3,a[2]的地址是ffc5。因此a == &a[0],即第一個元素的地址就是整個數組的地址
[數組名代表的就是數組的地址,也就是第0個元素的地址;]
*初始化:int a[2]={1,2}(可省略size和和第一個元素後的元素);或 a[0]=1,a[1]=[2];

** 一維數組的元素作爲函數實參,與同類型的簡單變量作爲實參一樣,是單向的值傳遞,即數組元素的值傳給形參,形參的改變不影響實參;
但是,如果一維數組的名字作爲函數實參,傳遞的是整個數組,即形參數組和實參數組完全等同,是存放在同一存儲空間的同一個數組。這樣形參數組修改時,實參數組也同時被修改了。形參數組的元素個數可以省略。
[* 此處同java *]

  • 二維數組
    是一個特殊的一維數組,元素是一個一維數組;存放的順序是一行行的存;
    a[0]、a[1]也是數組,是一維數組,而且a[0]、a[1]就是數組名,因此a[0]、a[1]就代表着這個一維數組的地址;a = a[0][0];
    [若只初始化了部分元素,可省略行數,但不能省略列數;]

  • 字符串
    沒有String類型,使用字符數組來存儲字符串;
    ** 字符串可以看做是一個特殊的字符數組,爲了跟普通的字符數組區分開來,應該在字符串的尾部添加了一個結束標誌’\0’。’\0’是一個ASCII碼值爲0的字符,是一個空操作符,表示什麼也不幹。所以採用字符數組存放字符串,賦值時應包含結束標誌’\0’。
    [NOTE:尾部有個’\0’,如果沒有這個結束標記,說明這個字符數組存儲的並不是字符串]

初始化:一般使用 char s[] =“mj”;會自動在末尾添加’\0’;
若使用char s[]={‘m’,’j’,’\0’};一定要加’\0’;否則會造成內存地址錯誤,內存泄露,讀到髒數據;
== puts(s)== 輸出字符串:會從起始地址一直打印到’\0’止,故若定義時沒有’\0’,則很可能會出現內存泄露(很危險)
== gets(s)== 輸入字符串:從s的地址開始逐個賦值用戶輸入的字符,並自動加上\0,故兩個s一起打印,會讀到其他數據(很危險),
(gets一次只能讀取一個字符串,scanf則可以同時讀取多個字符串;
gets可以讀入包含空格、tab的字符串,直到遇到回車爲止;scanf不能用來讀取空格、tab

+字符串數組
一維字符給存放一個字符串;

+字符串處理函數
== putchar(‘A’)==:輸出一個char字符;
== char c;c=getchar()==:輸入一個char字符;
== strlen(s) ==:測量字符個數,但不包括\0;
== strcpy(s1,s2)==:將右邊的s2字符串拷貝到字符數組s1中。從s1的首地址開始,逐個字符拷貝,直到拷貝到\0爲止。當然,在s1的尾部肯定會保留一個\0。[原s1中的內容會被清掉]
== strcat(s1,s2)==:把s2拼接到s1的後面,從首地址開始到第一個’\0’就認爲是字符串末尾,而不管後面是否還有內容如(char s[]={‘a’,’\0’,’b’})[但必須要保證s1有足夠的長度來存儲s2,否則會內存溢出。];
== strcmp(s1,s2)==:根據字符的ASCII碼的大小來比較兩個字符串的大小;大於爲1,等於爲0,小於爲-1;
== strlwr(s)==:將字符串中的大寫轉成小寫;

感謝李明傑老師@M了個J的講解及時詳細的課件(http://www.cnblogs.com/mjios)!

博客地址:IOS基礎學習之C(一)

發佈了46 篇原創文章 · 獲贊 7 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章