Object-C 語言是C語言的超集,意思就是咱們可以將兩種語言寫在同一個源碼文件裏。java
Object-C語言結構的核心是創建在C語言之上的。因此在學習語言的高級特性以前,掌握C語言基礎是很是重要的。objective-c
這個模塊爲C語言提供一個簡潔的概述。咱們將討論關於凝視、變量、算數運算符、控制流、簡單的數據結構、指針。編程
這些概念是咱們討論Object-C面向對象特性的基礎。數組
在C語言中有兩種方式可以提供凝視。行內凝視。以雙斜線開始,到本行結束。markdown
塊凝視,可以跨越多行,但是必須在 /* 和 */ 之間。
比方:數據結構
// This is an inline comment
/* This is a block comment. It can span multiple lines. */
因爲編譯器會忽略凝視,這樣就可以讓咱們在代碼的旁邊加入額外的信息。這樣可以幫助咱們解釋一些easy誤解的代碼,Object-C代碼基本是自解釋的。因此您不是很是需要在IOS 和 OS X 應用加入太多的凝視。框架
變量是一個容器。他可以存儲不一樣的值。dom
在C語言中,變量類型是靜態的,意思就是您必須清楚的聲明。您想存儲什麼類型的值。聲明變量的語法爲: ,給變量賦值用=操做符。ide
假設您想將一個變量轉化成還有一個類型,您可以在變量前加入括號,括號里加入新類型。函數
所有的都在如下的代碼中演示了。聲明瞭一個 odometer 變量,可以存儲double類型的變量。 (int)odometer 的聲明將轉化odometer 存儲的值 爲一個int類型。假設您將代碼粘貼在main.m文件裏。執行程序。
您將在輸出面板中看到NSLog()中的消息。
// main.m
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
@autoreleasepool {
double odometer = 9200.8;
int odometerAsInteger = (int)odometer;
NSLog(@"You've driven %.1f miles", odometer); // 9200.8
NSLog(@"You've driven %d miles", odometerAsInteger); // 9200
}
return 0;
}
像double和int同樣。C語言定義了很是多原生的數據類型。
一個完整的列表可以在原生模塊中找到。而且上面用到的the %.1f 和 %d 格式化符號也有解釋。
常量修飾符是告訴編譯器,這個變量是不能被改動的。比方定義一個變量叫pi,假設您試圖改動它,將會致使編譯器報錯。
double const pi = 3.14159;
pi = 42001.0; // Compiler error
這個通常是用在函數的參數中。告訴函數的調用者,他們可以假設傳遞給函數的參數是不會被改動的。
咱們熟悉的+, -, *, /符號是用來作主要的算數運算符。模運算符(%)被用來返回整數相除的餘數。
如下是演示:
NSLog(@"6 + 2 = %d", 6 + 2); // 8
NSLog(@"6 - 2 = %d", 6 - 2); // 4
NSLog(@"6 * 2 = %d", 6 * 2); // 12
NSLog(@"6 / 2 = %d", 6 / 2); // 3
NSLog(@"6 %% 2 = %d", 6 % 2); // 0
當涉及到浮點數或者整數操做時,要特別的當心。具體信息請看整數相除。
當您使用循環時,經常遇到++ 或者–操做符。他是一個從變量中減一或者加一的簡易的符號。
int i = 0;
NSLog(@"%d", i); // 0
i++;
NSLog(@"%d", i); // 1
i++;
NSLog(@"%d", i); // 2
像其它的語言同樣C語言也提供了標註的if聲明。他的主要的語法,以及一個用於描寫敘述邏輯運算符的表,例如如下所看到的:
int modelYear = 1990;
if (modelYear < 1967) {
NSLog(@"That car is an antique!!!");
} else if (modelYear <= 1991) {
NSLog(@"That car is a classic!");
} else if (modelYear == 2013) {
NSLog(@"That's a brand new car!");
} else {
NSLog(@"There's nothing special about that car.");
}
Operator Description
a == b Equal to
a != b Not equal to
a > b Greater than
a >= b Greater than or equal to
a < b Less than
a <= b Less than or equal to
!a Logical negation
a && b Logical and
a || b Logical or
C語言也提供了 switch 聲明,但是參數僅僅能是整數,不能是浮點數、指針或者其它的Object-C對象。與if條件語句相比較,至關的不靈活。
// Switch statements (only work with integral types)
switch (modelYear) {
case 1987:
NSLog(@"Your car is from 1987.");
break;
case 1988:
NSLog(@"Your car is from 1988.");
break;
case 1989:
case 1990:
NSLog(@"Your car is from 1989 or 1990.");
break;
default:
NSLog(@"I have no idea when your car was made.");
break;
}
while 和 for 循環可以迭代一些值。相關的break 和continue可以對應使退出循環,或者跳過一個迭代
int modelYear = 1990;
// While loops
int i = 0;
while (i<5) {
if (i == 3) {
NSLog(@"Aborting the while-loop");
break;
}
NSLog(@"Current year: %d", modelYear + i);
i++;
}
// For loops
for (int i=0; i<5; i++) {
if (i == 3) {
NSLog(@"Skipping a for-loop iteration");
continue;
}
NSLog(@"Current year: %d", modelYear + i);
}
現在是合適的時間介紹for-in循環,然而這並不是C語言的。這個稱爲高速枚舉語法,因爲相比傳統的for和while循序。它是一種更加有效的迭代Object-C集合的方法。比方NSSet 和NSArray 。
// For-in loops ("Fast-enumeration," specific to Objective-C)
NSArray *models = @[@"Ford", @"Honda", @"Nissan", @"Porsche"];
for (id model in models) {
NSLog(@"%@", model);
}
Macros are a low-level way to define symbolic constants and space-saving abbreviations. The #define directive maps a macro name to an expansion, which is an arbitrary sequence of characters. Before the compiler tries to parse the code, the preprocessor replaces all occurrences of the macro name with its expansion. In other words, it’s a straightforward search-and-replace:
宏指令是一個定義符號常量和別名的底層方法。
// main.m
import
int main(int argc, const char * argv[]) {
@autoreleasepool {
double angle = PI / 2; // 1.570795
NSLog(@"%f", RAD_TO_DEG(angle)); // 90.0
}
return 0;
}
This code snippet demonstrates the two types of C macros: object-like macros (PI) and function-like macros (RAD_TO_DEG(radians)). The only difference is that the latter is smart enough to accept arguments and alter their expansions accordingly.
Typedef可以使咱們定義一個新的數據類型或者又一次定義一個已經存在的數據類型。
如下演示一個無符號字符的typeof定義,咱們可以使用ColorComponent 就像咱們是用char、int、double和其它內建數據類型。
// main.m
import
int main(int argc, const char * argv[]) {
@autoreleasepool {
ColorComponent red = 255;
ColorComponent green = 160;
ColorComponent blue = 0;
NSLog(@"Your paint job is (R: %hhu, G: %hhu, B: %hhu)",
red, green, blue);
}
return 0;
}
typedef 一般被用做將struct或者enum轉化成更加方便的數據類型。這個被演示在如下兩個段落。
struct 像一個簡單的、原生的C對象。它可以讓你聚合一些變量在一個比較複雜的數據結構,但是它不提供面向對象編程的特性,比方方法。比方,如下的代碼片斷使用struct聚合了組成RGB的元素。
注意。咱們經過typeof。可以經過更加有意義的名字獲取。
// main.m
import <Foundation/Foundation.h>
typedef struct {
unsigned char red;
unsigned char green;
unsigned char blue;
} Color;
int main(int argc, const char * argv[]) {
@autoreleasepool {
Color carColor = {255, 160, 0};
NSLog(@"Your paint job is (R: %hhu, G: %hhu, B: %hhu)",
carColor.red, carColor.green, carColor.blue);
}
return 0;
}
咱們使用了{255, 160, 0}的初始化語法,來初始化新的carColor 結構體。這個複製的順序和咱們定義struct的順序同樣。
而且咱們可以經過點語法獲取每一個域。
enum 關鍵字被用於定義枚舉類型,他是一個相關常量的集合。
像struct,經過typedef定義個更加有描寫敘述性的名字。
// main.m
import <Foundation/Foundation.h>
typedef enum {
FORD,
HONDA,
NISSAN,
PORSCHE
} CarModel;
int main(int argc, const char * argv[]) {
@autoreleasepool {
CarModel myCar = NISSAN;
switch (myCar) {
case FORD:
case PORSCHE:
NSLog(@"You like Western cars?"); break; case HONDA: case NISSAN: NSLog(@"You like Japanese cars?"); break; default: break; } } return 0; }
覺得myCar 變量被定義爲CarModel 類型。因此他僅僅能存儲四種類型的枚舉成員: FORD, HONDA, NISSAN, and PORSCHE。
定義這些在一個枚舉類型中,比使用字符串表明各類CarModel更加的可靠。
Cocoa 框架使用大量的枚舉定義常量。比方NSSearchPathDirectory 定義OS X使用的 標準文件夾路徑。
Ry’s Cocoa的教程。數據存儲章節中提供了大量的樣例。
因爲Object-C是C語言的超級,它就可以訪問C語言中的數組。Foundation 提供的NSArray 和 NSMutableArray 比C 語言的數組更加的方便好用。
然而,對性能要求比較高的環境,C語言數組仍是很是實用的。
int years[4] = {1968, 1970, 1989, 1999};
years[0] = 1967;
for (int i=0; i<4; i++) {
NSLog(@"The year at index %d is: %d", i, years[i]); }
years[4] 聲明分配了可以存儲四個int值得連續內存空間。
咱們使用 {1968, …}的初始化語法初始化了數組,咱們可以經過傳遞偏移在方括號裏獲取數組的元素值。
指針是一個內存地址的引用。
指針刪除了一個抽象層、是你可以看到。數值是如何存儲的。
這樣需要兩個工具。
引用操做符可以返回變量內存地址。
這樣你就可以建立一個指針。
解引用操做符可以返回內存地址的存儲內容。
如下演示了,如何申明、建立、解除指針。注意一個指針就像定義一個一般的變量。但是就是在變量以前加入了*。
int year = 1967; // Define a normal variable
int *pointer; // Declare a pointer that points to an int
pointer = &year; // Find the memory address of the variable
NSLog(@"%d", *pointer); // Dereference the address to get its value
*pointer = 1990; // Assign a new value to the memory address
NSLog(@"%d", year); // Access the value via the variable
指針圖形化的表演示樣例如如下:
上面的樣例,指針僅僅是一個非必須的變量的抽象。他的實際的用處。你可以在附近移動指針。
尤爲是遍歷數組,一個連續的內存空間。比方線面,經過指針迭代數組元素。
char model[5] = {'H', 'o', 'n', 'd', 'a'};
char *modelPointer = &model[0];
for (int i=0; i<5; i++) {
NSLog(@"Value at memory address %p is %c", modelPointer, *modelPointer); modelPointer++; } NSLog(@"The first letter is %c", *(modelPointer - 5));
當咱們使用指針。++操做符將移動指針到下一個地址,咱們可以輸出地址經過含有%p修飾符NSLog。
相同,–操做符被用做減指針到以前的地址。
如上所看到的,您可以訪問相對當前地址的不論什麼地址。
空指針是一個特殊的指針,不指向不論什麼地址。
C語言中僅僅有一個空指針。他的類型是NULL 宏。主要表示變量爲空,變量不能有一個正常的值。比方所看到的,經過空指正置空一個指針。
int year = 1967;
int *pointer = &year;
NSLog(@"%d", *pointer); // Do something with the value
pointer = NULL; // Then invalidate it
咱們表示year 爲空變量,可以經過設置爲0實現,但是,對於year也是一個正常的值,而不是缺乏值。
void 類型的指針是一個通用類型。它可以指向不論什麼地址。所以,咱們需要將void類型的指針轉化成非void類型的指針。比方, (int *)申明將指正轉化成int類型的指正。
int year = 1967;
void *genericPointer = &year;
int *intPointer = (int *)genericPointer;
NSLog(@"%d", *intPointer);
void 類型指正提供了很是多的靈活性。比方NSString 類定義例如如下方法。將C數組轉化成Object-C的字符串。
- (id)initWithBytes:(const void *)bytes length:(NSUInteger)length encoding:(NSStringEncoding)encoding
bytes 參數指向C數組的內存第一個地址。length參數執行讀取多少字節,encoding 參數如何解析字節。使用void類型的指針,這樣bytes參數可以是不論什麼字符數組。
這是一些背景知識。但是您平常的Object-C開發中並不需要。咱們必須理解。Object-C中的每一個對象都是經過指針引用的。
比方,NSString 類型變量必須存儲一個指針,而不是一個主要的變量。
NSString *model = @"Honda";
空指針在Object-C和C中是不同的,在C中使用NULL。Object-C定義可本身的宏,nil,他是空。重要經驗是,在引用Object-C對象指針中使用nil。而對於C指針使用NULL。
NSString *anObject; // An Objective-C object
anObject = NULL; // This will work
anObject = nil; // But this is preferred
int *aPointer; // A plain old C pointer
aPointer = nil; // Don't do this
aPointer = NULL; // Do this instead
整個Object-C語法都是和指正相關的。
定義了一對象指針以後,您基本就忘記了他是一個指針,因爲使用和其它的變量同樣。
咱們將經過本教程的大量樣例理解清楚。
本章主要解說C語言的基礎。
主要是想讓你們熟悉變量、條件、循環、結構體、枚舉、和指針。這些工具是構成不論什麼Object-C程序的基礎。
Object-C依賴C的這些基礎結構。而且給與直接加入C++代碼的選擇。爲了告訴編譯器,編譯的是C、C++或者Object-C,您可以將源碼的文件擴展名改動爲.mm。
這個獨特的語言特徵。打開了整個C/C++的大門,這是對於Object-C開發人員最大的恩惠。比方。您在開發IOS遊戲,發現本身需要一個物理引擎,你可以使用註明的Box2D 包。不需要額外的工做。
下一章咱們將經過學習函數,結束C語言的學習。在這以後,咱們已經準備好學習Object-C類、方法、協議和其它面向對象的內容。