国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統 > iOS > 正文

IOS基礎學習之C(二)

2019-11-07 23:55:52
字體:
來源:轉載
供稿:網友

++ 指針 ++ 引用的概念:賦值時都是先將變量名a轉換為a的存儲地址,根據地址找到變量a的存儲空間。然后將數據以2進制的形式放入a存儲空間中。

c_111.png

直接引用:直接通過變量名來讀寫變量

間接引用:首先將變量a的地址存放在另一個變量中,比如存放在變量b中,然后通過變量b來間接引用變量a,間接讀寫變量a的值。 [間接引用來修改值:先根據 變量名b 獲取 變量b 的地址ffc2,取出變量b中存儲的內容ffc1,也就是變量a的地址,再根據變量a的地址ffc1找到a的存儲空間,然后修改里面的數據。] *指針變量:用來存放變量地址的變量,就稱為”指針變量”。在上面的情況下,變量b就是個”指針變量”,我們可以說指針變量b指向變量a。

char a; // a = 10;//該用方式是直接引用的方式;char *b;//定義了一個指針就是b,而且b只能指向char類型的變量;//讓指針變量b指向a; b = &a; //* 指針運算符,*b代表訪問b中存儲的地址對應的存儲空間;也就變量a的存儲空間 //此處*b中的*與char *b中的*的定義是不一樣的,這里為操作符,上面的只是定義; //相當于a=10; *b =10; 以值交換的例子說明:若參數直接傳入變量值,交換后不能改變傳入變量的值;只有傳入的是原參數的地址,用地址交換,才能改變原傳入參數的值。

void swapPoint(char *a,char *b){ printf("swap交換前的值%d,%d/n",*a,*b); char temp= *a; *a=*b; *b=temp; printf("swap交換后的值%d,%d/n",*a,*b);}

** 使用指針可在函數內部修改外變量的值

int sumAndMinus(int a,int b,int *minus){ *minus = a-b; return a+b;}

利用返回一個值,傳入另外參數的地址,便可同時修改多個值。[常用] 注意: 在同一種編譯器環境下,一個指針變量所占用的內存空間是固定的。比如,在16位編譯器環境下,任何一個指針變量都只占用2個字節,并不會隨所指向變量的類型而改變。 既然每個指針變量所占用的內存空間是一樣的,而且存儲的都是地址,為何指針變量還要分類型?而且只能指向一種類型的變量?比如指向int類型的指針、指向char類型的指針。 [這個問題跟”數組為什么要分類型”是一樣的。由于指針的長度是由編譯器決定的和類型沒有關系,但定義的類型不一樣時會認為要取出的內容就是定義的類型的長度。如char c;int *p=&c;就會認為c的值是占用兩個字節,便從c的起始地址取兩個字節,但c的值實際上只有一個字節,于是就會取出錯誤的值。]

++ 指向一維數組的指針 組及其數組元素都占有存儲空間,都有自己的地址,因此指針變量可以指向整個數組,也可以指向數組元素。

int a[2];int *p; p=a與p=&a[0];相同;

void traversalArray(){ int a[3]={1,2,3}; int *p = a;//讓指針指向第一個指針; for(int i=0;i<3;i++){ //由于在數組中地址是連續的,p+i即可取出地址,*(p+i)即可取出對應的值 //對于指針類型來說p+1,不只是純粹的地址+1;而是和指向的類型有關,+1是+該類型的字節對應的地址字節個數;如float類型,即p+4; // printf("a[%d]=%d/n",i,*(p+i));//p的地址和值都未改變 // printf("a[%d]=%d/n",i,*(a+i));//原理同上,但不能寫成a++;不能改變數組的首地址; printf("a[%d]=%d/n",i,*(p++)); //p的地址和值一直會改變 printf("p的地址:%d,p的值%d/n",p,*p); }}

若一個函數的參數是一個數組或一個指針變量,都可以傳數組名或數組的指針;

blob19.png

++ 指針和字符串 ++ 定義: char *s=“mj”;或char *s;s=“mj”; [錯誤寫法:char s[10];s=“mj”;或char *s =”mj”;*s=“jm”(*s=‘f’;此處s是一個常量不能修改,但char s[]=“mj”,此處是一個變量,可直接修改);均是錯誤寫法。]

++ 指針函數++ 函數作為一段程序,在內存中也要占據部分存儲空間,它也有一個起始地址,即函數的入口地址。可以利用一個指針指向一個函數。其中,函數名就代表著函數的地址。 定義: 可將函數作為為參數傳入另一個函數并進行調用。

char * point(){ return "返回指針的函數/n";}int sum(int a,int b){ printf("sum %d/n",a+b); return a+b;}/*將另外一個函數做為參數(可類似于
java中的接口使用)*/int count(int a,int b,int(*p)(int,int)){ return p(a,b);}void testPointVoid(){// printf(point()); //定義了一個指向函數的指針變量p; //被p指向的函數,返回的值為int類型,接收兩個int類型的參數 int (*p)(int,int); //讓指針變量p指向sum函數; p=sum; //利用指針變量間接調用sum函數// (*p)(5,6); //或 p(5,6); //將求和的方法名傳入到方法中進行計算 int result = count(5, 6, sum); printf("result:%d/n",result);}

++ 預處理指令 ++ 概述: 1.C語言在對源程序進行編譯之前,會先對一些特殊的預處理指令作解釋(比如之前使用的#include文件包含指令),產生一個新的源程序(這個過程稱為編譯預處理),之后再進行通常的編譯 2.為了區分預處理指令和一般的C語句,所有預處理指令都以符號”#”開頭,并且結尾不用分號 3.預處理指令可以出現在程序的任何位置,它的作用范圍是從它出現的位置到文件尾。習慣上我們盡可能將預處理指令寫在源程序開頭,這種情況下,它的作用范圍就是整個源程序文件 4.C語言提供的預處理指令主要有:宏定義(*define文件包含(include)條件編譯* ** 宏定義:類似java中的final,一定定義不變的變量,如

#define NUM 6#define KEY “Name"

還可以定義一個方法,如: //若定義帶參數的宏方法,最好用括號括起來(每個元素及整體都需要),因為宏計算只是簡單的拼接計算

//#define mul(a,b) a*b//如mul(3-2,4-3)為3-2*4-3,則計算錯誤#define mul(a,b) ((a)*(b))

[NOTE:但與函數不一樣,因為宏是在編譯前已經計算,而函數是在使用時再計算,故為了效率,簡單的運算可放在宏方法了;另,宏定義不會檢測數據類型,也沒有返回值;名字如上mul不是函數的地址;] ** 條件編譯:在很多情況下,我們希望程序的其中一部分代碼只有在滿足一定條件時才進行編譯,否則不參與編譯(只有參與編譯的代碼最終才能被執行),這就是條件編譯

#if條件1 ..code1.. #elif2 ..code2.. #else ..code3.. #endif

就只是編譯滿足條件的代碼,是編譯而不執行。與平時用的if-else不一樣。 (一定要寫#endif,表示和#if這間的內容才是條件編譯,一般與宏定義的值配合使用,只編譯部分代碼,效率很高。)

#if NUM>6 printf("num>6");#elif NUM==6 printf("num=6");#else printf("num<6");#endif

其他用法:

#if defined(MAX)//是否定義過某個宏 ...code... #endif

或者:

#ifdef MAX //同上,表示是否定義過宏MAX …code... #endif#ifndef MAX//同上,表示沒有定義過宏MAX ...code... #endif
include 允許嵌套包含,但不允許遞歸包含;可能導致多次包含同一個頭文件,降低編譯效率。 為了解決重復導入包,使用條件編譯://若沒有該宏,就定義該宏,然后在該條件內定義函數名,宏名一般同頭文件名 #ifndef Header_h #define Header_h ... #endif /* Header_h */

++ 變量類型 ++ 變量的存儲類型:指變量存儲在什么地方。有3個地方可以用于存儲變量:普通內存(靜態)、運行時堆棧(動態)、硬件寄存器。變量的存儲類型決定了變量何時創建、何時銷毀以及它的值能保持多久,也就是決定了變量的生命周期。 C語言根據變量的存儲類型的不同,可以把變量分為:自動變量、靜態變量、寄存器變量。 — 自動變量:存儲在堆棧中的; 哪些是自動變量:被關鍵字auto修飾的局部變量都是自動變量,但是極少使用這個關鍵字,基本上是廢的,因為所有的局部變量在默認情況下都是自動變量。 生命周期:在程序執行到聲明自動變量的代碼塊(函數)時,自動變量才被創建;當自動變量所在的代碼塊(函數)執行完畢后,這些自動變量就會自行銷毀。如果一個函數被重復調用,這些自動變量每次都會重新創建。 — 靜態變量:靜態變量是存儲在靜態內存中的,也就是不屬于堆棧。(與java中的靜態變量不同) 哪些是靜態變量: ? 所有的全局變量都是靜態變量(不用static修飾) ? 被關鍵字static修飾的局部變量也是靜態變量(只改變了其生命周期,但未改變其作用域) 生命周期:靜態變量在程序運行之前創建,在程序的整個運行期間始終存在,直到程序結束。 — 寄存器變量:存儲在硬件寄存器中的變量,稱為寄存器變量。寄存器變量比存儲在內存中的變量訪問效率更高(默認情況下,自動變量和靜態變量都是放在內存中的) 哪些是寄存器變量: ? 被關鍵字register修飾的自動變量都是寄存器變量 ? 只有自動變量才可以是寄存器變量,全局變量和靜態局部變量不行 ? 寄存器變量只限于int、char和指針類型變量使用 生命周期:因為寄存器變量本身就是自動變量,所以函數中的寄存器變量在調用該函數時占用寄存器中存放的值,當函數結束時釋放寄存器,變量消失。 使用注意: ? 由于計算機中寄存器數目有限,不能使用太多的寄存器變量。如果寄存器使用飽和時,程序將寄存器變量自動轉換為自動變量處理 ? 為了提高運算速度,一般會將一些頻繁使用的自動變量定義為寄存器變量,這樣程序盡可能地為它分配寄存器存放,而不用內存

關鍵字 extern 與 static+ 不僅可用在變量上,還可以用在函數上。 ++ extern與函數 ++ ? 外部函數:如果在當前文件中定義的函數允許其他文件訪問、調用,就稱為外部函數。C語言規定,不允許有同名的外部函數。 ? 內部函數:如果在當前文件中定義的函數不允許其他文件訪問、調用,只能在內部使用,就稱為內部函數。C語言規定不同的源文件可以有同名的內部函數,并且互不干擾。 [extern即外部函數,但默認的都是外部函數,故可省略extern] ++ static void one(){..};內部函數,需要使用static修飾;外部不能直接調用;只能是內部調用,相當于private; 總結: — static — 在定義函數時,在函數的最左邊加上static可以把該函數聲明為內部函數(又叫靜態函數),這樣該函數就只能在其定義所在的文件中使用。如果在不同的文件中有同名的內部函數,則互不干擾。 static也可以用來聲明一個內部函數 —— extern — 在定義函數時,如果在函數的最左邊加上關鍵字extern,則表示此函數是外部函數,可供其他文件調用。C語言規定,如果在定義函數時省略extern,則默認為外部函數。 在一個文件中要調用其他文件中的外部函數,則需要在當前文件中用extern聲明該外部函數,然后就可以使用,這里的extern也可以省略。 [定義只保證編譯時通過] ++ extern、static與變量的關系 ++ C與Java都有全局變量的概念;但有一些不同: 默認情況下,一個函數不可訪問在它后面定義的全局變量;extern int a;//此處是用來聲明一個變量,不能直接賦值和使用,只保證語法正確,聲明后要以調用后去定義該變量int a;//此處是用來定義一個變量可直接使用

在方法中使用 extern int a;//表示引用的是方法外部的全局變量 — extern —:只能用來聲明全局變量,不能用來定義全局變量。 C中不同的源文件中可以有相同名字的變量,同一個文件中也有可多個相同名字的變量。默認情況下這些變量代表著同一個變量(默認情況下都是外部變量)[也可以文件a中的聲明,文件b中定義] — static —: static int a;//定義的全局變量,相當于定義了私有的全局變量(類似于java中的private);在不同一源文件下相同的變量名,若用static修飾,即限制全局變量的作用域,則互不影響,是不同的變量。

++ 結構體 ++ 問題:當一個整體由多個數據構成時,我們可以用數組來表示這個整體,但是數組有個特點:內部的每一個元素都必須是相同類型的數據。但在實際應用中,我們通常需要由不同類型的數據來構成一個整體。 為解決這個問題:C提供了一種構造類型來解決,就是結構體。它允許內部的元素是不同類型的。 struct Student { char *name; // 姓名 int age; // 年齡 float height; // 身高 };。 [只定義了一個結構體類型并沒有對其分配存儲空間,只有在其定義一個結構體變量后才會分配一個存儲空間] 定義結構體變量的3種方式: * struct Student stu; * struct Student{…}stu; * struct{…}stu; 賦值: struct Student stu={“tom”,12,1.67}; 或stu.age=12; 注意點: * 不能對結構體本身遞歸定義; * 結構體內可以包含別的結構體; * 結構體變量占用的內存空間是其所有成員所占內存之和,而且各成員在內存中按定義的的順序依次排列。

//要么全部放在大括號中,在定義的時候就賦值;要么所有的都單獨賦值;不能一部分在定義的賦值,一部分單獨賦值 struct Student stu={13,"tom",1.76,{1990,10,10}};

定義結構體數組同一般類型;也能作為方法參數; 若將結構體做函數參數,只改變函數內結構體的值,傳入的結構體值為變(同java傳入類作形參); 要改變原結構的值,可傳入結構體變量的指針;

void changPoint(struct Student *stu){ (*stu).age=9; (*stu).name="jim”; (*stu).height=2.01;}

//調用: changPoint(&stu); 訪問方式(3種): // 方式1:結構體變量名.成員名 printf(“name=%s, age = %d /n”, stu.name, stu.age); // 方式2:(*指針變量名).成員名 printf(“name=%s, age = %d /n”, (*p).name, (*p).age); // 方式3:指針變量名->成員名 printf(“name=%s, age = %d /n”, p->name, p->age);

++ 枚舉 ++ 同Java,一般用于固定常量;enum Season{spring,summer,autumn,winter}; 便不同于java的是,枚舉變量可直接賦其他值,而非枚舉值。

//enum Season{spring,summer,autumn,winter}s;//定義枚舉類型的同時定義一個枚舉變量senum Season{spring,summer,autumn,winter}s=spring;enum Season{spring=1,summe=2,autumn,winter};

注意:C編譯器一般會將枚舉作為整型常量處理,稱為枚舉常量; 枚舉的值取決于定義時向枚舉元素的先后順序,默認情況下,第一個枚舉元素值為0;可自己設置;

++ typedef++ 用于為各種數據定義一個新名字(別名)。 如:typedef unsigned int UInteger;//無符號整型 可在另外的基礎上再定義一個別名: 如:typedef UInteger MyInteger; 可修飾指針; 如:typedef char * String; 可定義結構體及指針;

typedef struct Student Stu;typedef struct Student * StuPoint;typedef struct{ float x; float y;} Point;typedef struct Point{ float x; float y;} *PP;

修飾枚舉:typedef enum {spring,summer,autumn,winter} Season; Season s=spring;

修飾函數的指針;(不是很常用)

static int sum(int a,int b){ return a+b;}static int cul(int a,int b){ return a*b;}typedef int (*CountPoint)(int,int);void testtypedef(){ CountPoint sunpoint = sum; CountPoint culpoint = cul; printf("sum:%d/n",(*sunpoint)(4,5)); printf("cul:%d/n",(*culpoint)(4,5));}

typedef與#define 區別:typedef,是新定義了一個類型,而宏定義是將變量拼接到定義后;若起別名一般使用typedef,而非define 區別:typedef,是新定義了一個類型,而宏定義是將變量拼接到定義后;若起別名一般使用typedef,而非define

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

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


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 同心县| 喀什市| 永修县| 晋州市| 五大连池市| 多伦县| 平舆县| 石河子市| 思茅市| 河间市| 莲花县| 福建省| 肇源县| 揭西县| 荔浦县| 丰都县| 瑞丽市| 绵竹市| 丰县| 基隆市| 老河口市| 密云县| 江陵县| 宽城| 万安县| 灵川县| 蒙山县| 南郑县| 商都县| 泰州市| 新疆| 江永县| 奇台县| 尉犁县| 德州市| 牙克石市| 竹溪县| 杂多县| 新巴尔虎左旗| 营口市| 新民市|