1.什麼是地址: 我們說變量都有自己的地址, 計算機要找到某個變量,必須知道該變量的地址.我們可以通過 & 獲得變量地址
取地址符 : & 通過取地址符就能把變量的地址給取出來.
int main(int argc, const char * argv[])
{
int a;
printf("%p\n", &a);//輸出變量a的地址
return 0;
}
2.什麼是指針?
假如我們擁有很多客戶的地址, 那麼我們需要一個通訊錄來保存這些客戶的地址, 同樣對於計算機來說, 也需要用一個工具來保存變量的地址, 那麼這個工具,就是指針
指針就是用來保存內存地址的變量,本質是變量,變量存放的是地址,指針變量同樣具有變量名,變量類型,變量值
我們可以通過圖形來表示
指針定義:
一般形式: 類型 * 標示符
標示符: 表示指針變量的名字
類型: 表示指針指向的數據類型
int main(int argc, const char *argv[])
{
int a;
int *p;// 定義一個指針類型的變量p
p= &a;//取出a的地址賦值給指針p
printf("%p\n", p);
printf("%p\n", &a);
return 0;
}
3.間接尋址符: *
通過指針進行讀取
如果知道圖書館的地址, 那麼我們可以找到圖書館,並在圖書館內閱覽;
同理, 如果指針p保存了變量a的地址, 那麼就可以通過指針p來找到變量a, 並讀取變量a 的值
通過指針進行修改
只要知道某一個人的地址, 那麼我們就能找到這個人
同理, 知道變量的地址,那麼我們就能修改變量的值
/*
int main(int argc, const char *argv[])
{
int a= 10;
int *p= &a;
printf("a== %d\n", *p);
return 0;
}
*/
int main(int argc, const char *argv[])
{
int a= 10;
int *p= &a;//取出地址並賦值
*p = 20;//修改變量a的值
printf("a == %d", a);
return 0;
}
4.void * 指針
#define NULL ((void *) 0)
空指針 NULL #define NULL ((void *)0)
指針就是用來保存內存地址的變量, 因此定義一個指針後一定要用它來保存一個內存地址, 假如不那麼做, 那麼該指針就是一個野指針, 它的默認值是隨機的, 因此會造成混亂
int main(int argc, const char *argv[])
{
int a = 10;
char ch = 'a';
void *p=&a;
void *q = &ch;
// *p = 10;
printf("%d\n", *(int *)p);
printf("%c\n",*(char *)q);
//printf("%d", *p);
return 0;
}
5.野指針
(1)當一個指針指向內容非法時, 那這就是一個野指針
(2)定義一個指針沒有賦初值, 這個指針就是野指針
(3)一個指針指向的內容被銷燬了,這個指針就是野指針
int main(int argc, const char *argv[])
{
int *p=NULL;//undefine
*p = 10;
printf("%d\n",*p);
return 0;
}
6.指針與函數
//指針變量作爲函數參數
//封裝一個函數交換兩個值
void swap(int a, int b)
{
int temp;
temp = a;
a = b;
b = temp;
return ;
}
int main(int argc, const char *argv[])
{
int a = 10;
int b = 20;
printf("交換前 a== %d b== %d\n", a, b);
swap(a, b);
printf("交換後 a== %d b== %d\n", a, b);
return 0;
}
問題:
思考下爲什麼上面的函數值沒有交換過來呢
用什麼方法能夠解決這個問題呢?(值傳遞,址傳遞!)
//使用指針變量作爲參數
void swap(int *a , int *b)
{
int temp;
temp = *a;
*a = *b;
*b = temp;
return ;
}
int main(int argc, const char *argv[])
{
int a= 10, b= 20;
printf("交換前 a== %d b== %d\n", a, b);
//傳遞變量的地址
swap(&a, &b);
//結果交換過來了!
printf("交換後 a== %d b== %d\n", a, b);
return 0 ;
}
7.指針與數組
數組名就是數組的首元素地址,數組名是一個常量
//數組名就是數組的首元素地址,數組名是一個常量
/*int main(int argc, const char *argv[])
{
int a[5]={1, 2, 3, 4, 5};
printf("%p\n", a);
printf("%p\n", &a);
printf("%p\n", &a[0]);
return 0;
}*/
int main(int argc, const char *argv[])
{
int a[5]= {1, 2, 3, 4, 5};
int *p=a;//數組地址賦值給指針變量p
for (int i = 0; i<5; i++) {
//輸出每一個元素
printf("a[%d]==%d\n", i,*(p+i));
}
return 0;
}
//指針實現數組逆序
void func(int *a,int len)
{
int i;
int temp;
for (i=0; i<len/2; i++) {
//通過指針操作數組元素
temp = *(a+i);
*(a+i)=*(a+len-i-1);
*(a+len-i-1)=temp;
}
}
實例:編寫一個對整型數組排序的函數
//選擇排序法
void sort(int *src, int len)
{
int i, j, k,temp;
for (i = 0; i< len -1; i++) {
k = i;
for (j= i+1; j<len; j++) {
if(*(src+k) > *(src + j))
{
k = j;
}
}
if (k!=i) {
//通過指針操作數組元素
temp = *(src+k);
*(src+k)= *(src+i);
*(src+i)= temp;
}
}
}
int main(int argc, const char *argv[])
{
int a[5];
printf("請輸入5個整型數據: \n");
for (int i= 0; i< 5; i++) {
scanf("%d", &a[i]);
}
//傳遞數組
sort(a, 5);
for (int i= 0; i< 5; i++) {
printf("%d ", a[i]);
}
printf("\n");
return 0;
}