C語言專題-指針

  • 指針重要性:

表示一些復(fù)雜的數(shù)據(jù)結(jié)構(gòu)
快速的傳遞數(shù)據(jù)
使函數(shù)返回一個以上的值
能直接訪問硬件
能方便的處理字符串
是理解面向?qū)ο笳Z言中引用的基礎(chǔ)

c語言的靈魂

  • 指針的定義

  • 地址:

    • 內(nèi)存單元的編號

    • 從零開始的非負(fù)整數(shù)

    • 范圍:

  • 指針:

  • 指針就是地址,地址就是指針

  • 指針變量就是存放內(nèi)存單元編號的地址,活著說指針變量就是存放地址的變量

  • 指針和指針變量是兩個不同的概念

  • 但是要注意的是:通常我們敘述會把指針變量簡稱為指針

  • 指針的本質(zhì)就是操作受限的非負(fù)整數(shù)(為什么這么說,因為非負(fù)整數(shù)可以加減乘除,而指針不能加乘除,只能相減)

  • 指針的分類:

1基本類型的指針
int * p;//p是變量名字, int* 表示存放的存放的是int類型的數(shù)據(jù)
int i =3;
p=&i;//p是指針變量,并且p存放了普通變量i的地址,所以說p指向了普通變量i ,所以*p=i;或者說所有出現(xiàn)*p的地方都可以替代成i,所有出現(xiàn)i的地方都可以替代成 *p,*p就是以p的內(nèi)容為地址的變量

常見的錯誤寫法

錯誤寫法1:
int * p;
int i =5;
*p=i;//錯誤:因為*p就是以p的內(nèi)容為地址的變量,但是p沒有賦值,就是垃圾值,所以這里*p就是以這個垃圾值為地址的這個一個單元,這個地址我們并不知道,那么你要把i的值給這個我們不知道的單元,那么就會奔潰
錯誤寫法2:
int i =5;
int*p;
int *q;
p=&i;
*q=p;//同上的一個原因是q是沒有賦值,*q是垃圾值,原因二是*q和p的數(shù)據(jù)類型不一致
錯誤寫法2:
int i =5;
int*p;
int *q;
p=&i;
q=q;//這個沒錯,q是垃圾值,q賦值給p,p也變成垃圾值
printf(@"%d",*q);//這個就是錯的,q的空間數(shù)據(jù)本程序,所以本程序可以讀寫,但是如果q內(nèi)部是垃圾值,則本程序不能讀寫*q的內(nèi)容,因此此時 *q所代表的內(nèi)存單元的控制權(quán)限并沒有分配給本程序,所以本程序運行到此行就會出錯

附注:* 的含義

1 乘法
2 定義指針變量: int * p;//定義了一個名字叫p的變量,int表示p只能存放數(shù)據(jù)類型為int類型的地址
3 指針運算符,該運算符放在已經(jīng)定義好的指針變量前面,如果p是一個定義定義好的指針變量,則*p表示以p的內(nèi)容為地址的變量
2.指針和數(shù)組

1.指針和一維數(shù)組

#####數(shù)組名:

一維數(shù)組名是個指針常量,存放的是數(shù)組首個元素的地址,因為它是常量,所以不能被改變
#####下標(biāo)和指針的關(guān)系
如果p是個指針變量,則p[i] 永遠(yuǎn)等價于 *(p+i)

確定一個一維數(shù)組需要幾個參數(shù)[如果一個函數(shù)要處理一個一維數(shù)組,則需要接受該數(shù)組的哪些信息],答案是需要兩個參數(shù):第一個是數(shù)組第一個元素的地址,第二個是數(shù)組的長度
#####指針變量的運算

指針變量不能相加不能相乘也不能相除,只能減
如果兩個指針變量指向的是同一塊連續(xù)空間中的不同儲存單元,則這兩個指針變量才可以相減,一般只能是數(shù)組

int  i =5;
int j=10;
int a[5];
p=&a[1];
q=&a[4];
printf("相差幾個單元:%d",q-p);//3
#####一個指針到底占幾個字節(jié)
假設(shè)p指向char類型變量(char占一個字節(jié))
假設(shè)q指向int類型變量(int占四個字節(jié))
假設(shè)r指向doubel類型變量(doubel占八個字節(jié))
那么p q r本身所占的字節(jié)數(shù)是否一樣
答案是:q p r本身所占字節(jié)數(shù)都是一樣的,四個字節(jié)
總結(jié):
1.一個指針變量,無論他指向的變量占幾個字節(jié),該指針本身只占四個字節(jié),
2.一個變量的地址使用該變量的首字節(jié)的地址表示
原理是這樣,比如q指向int類型變量,其他p只保存了int所在四個字節(jié)內(nèi)存的第一個字節(jié),至于只保存了第一個字節(jié)但是卻能儲存四個字節(jié)的數(shù)據(jù),這是由數(shù)據(jù)類型int決定,就是從p保存的第一個字節(jié)開始往后計算四個字節(jié),對于doubel float也是一樣的,但是為什么p本身占四個字節(jié),這是因為,機器是32位的,也就說地址總線有32跟,那么最大地址的表示為2的32次方,也就是4個字節(jié)的表示方式,p表示其實都是內(nèi)存單元,既然內(nèi)存的最大單元為2的32次方法,那么它本身的最大值也應(yīng)該為2的32次方

2.指針和二維數(shù)組

3.指針和函數(shù)
4.指針和結(jié)構(gòu)體
  • 結(jié)構(gòu)體定義

為什么需要結(jié)構(gòu)體:為了表示一些復(fù)雜的事物,而普通的基本類型無法滿足實際需求
什么叫結(jié)構(gòu)體:就是把一些基本類型組合在一起的形成的新的數(shù)據(jù)類型叫做結(jié)構(gòu)體
```
//定義一個結(jié)構(gòu)體的數(shù)據(jù)類型
struct Student{
int age;
float score;
char sex;
};
struct student stu={12,"edison"};
NSLog(@"age =%d name=%s",stu.age,stu.name);

定義結(jié)構(gòu)體的方式

方式1:
struct Student{
int age;
float score;
char sex;
};
方式2:
struct Student{
int age;
float score;
char sex;
}stu;//在定義的同時直接定義變量名,這樣不好,因為只能定義一次
方法3:
struct{
int age;
float score;
char sex;
}stu;//也不好

 *  ######結(jié)構(gòu)體的初始化
初始化方法

方法1
struct student st ={12,"edison"};
方法2;
struct student st ;
st.age=12;
st.name="edison";

如何取出結(jié)構(gòu)體的每個成員

/*
結(jié)構(gòu)體變量名.成員名
指針變量名->成員名
/
struct student st={12,"edison"};
st.age=12;
st.name="name";
struct student * pst=&st;
pst->age=34;
pst->name="edison"http://pst->age 在計算機內(nèi)部會轉(zhuǎn)化成(
pst).age,
//所以 pst->age 等價于st.age,也等價于(*pst).age

*  ######結(jié)構(gòu)體運算
結(jié)構(gòu)體變量可以相互賦值

struct student st={12,"edison"};
st.age=12;
st.name="name";
struct student st2=st;//是可以的

#####5.多級指針
*  ####專題
#####1.動態(tài)內(nèi)存分配
*  ######傳統(tǒng)數(shù)組的缺點:
1.數(shù)組長度必須事先指定,且只能是常整數(shù),不能是變量
2.傳統(tǒng)形勢定義的數(shù)組,該數(shù)組的內(nèi)存程序員無法手動釋放,只能等本函數(shù)運行完畢由系統(tǒng)釋放
3.數(shù)組的長度一旦定義,其長度就不能更改,數(shù)組的長度不能在函數(shù)運行的過程中動態(tài)的擴充或者縮小
4.a函數(shù)定好的數(shù)組,在a函數(shù)運行期間可以被其他函數(shù)調(diào)用,但是a函數(shù)運行完畢之后,a函數(shù)中數(shù)組將無法給其他函數(shù)使用
*  ######為什么需要動態(tài)分配內(nèi)存
就是因為動態(tài)數(shù)組很好的解決了傳統(tǒng)數(shù)組的四個缺陷

int * p =(int )malloc(100);
/

malloc函數(shù)只有一個形參,就是需要分配的字節(jié)數(shù)
malloc函數(shù)其實只能返回分配好的內(nèi)存的第一個字節(jié)的地址,所以在malloc前加入(int *)強制轉(zhuǎn)化,就是為了表示把第一個字節(jié)的地址強制轉(zhuǎn)化成整形變量的地址,那么就說明這100個字節(jié)得按照4個字節(jié)一一劃分,
p本身所占的內(nèi)存是靜態(tài)分配的,p所指向的內(nèi)存是動態(tài)分配的
free(p);//把p指向的內(nèi)存給釋放掉,p本身的內(nèi)存是靜態(tài)的,不能由程序員手動釋放,把p指向的內(nèi)存釋放掉后就不能讀寫這塊內(nèi)存上的值了
*/

######1
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容