一級指針
指針是什麼
我們可以把宿舍樓裏面的每一個同學看成一個個的變量,存放在一個個宿舍裏,而爲了方便找到每個同學,我們給每個宿舍標號,而指針就是每個宿舍的門牌號,它的值直接指向地址所對應的變量單元。
爲什麼要有指針
很明顯我們找到一個個同學最快的方式就是通過宿舍門牌號,指針就是爲了能找到以它爲地址的內存單元。
總結:指針就是地址,指針變量就是變量,用來存放地址的變量(存放在指針裏的值都會被當成地址來處理)。注意:一個int型變量佔四個字節,每個字節都有一個地址,指針變量存放的是第一個地址。
代碼說明:
#incude <stdio.h>
int main()
{
int a=10;
int *p=&a;
return 0;
}
那麼在這段代碼裏,a的地址就是存放在變量p中的,p就是一個指針變量。
指針的大小
指針的大小在32位平臺上 是4個字節,在64位平臺上是8個字節。
指針的解引用
指針就是它指向的目標
int main()
{
int n = 0x11223344;
char *pc = (char *)&n;
int *pi = &n;
*pc = 0x55;
*pi = 0;
return 0;
}
總結:指針的類型決定對指針解引用的權限。char的指針解引用就只能訪問一個字節,而int的指針能訪問四個字節。
指針±整數
一句話:指針±1是±其所指元素的類型大小。所以多級指針±1都是±4個字節,因爲其所指類型都是指針。
下面來看一段代碼:
#include<stdio.h>
#include<stdlib.h>
int main()
{
int n = 10;
char *pc = (char *)&n;
int *pi = &n;
printf("%p\n", &n);//1
printf("%p\n", pc);//2
printf("%p\n", pc+1);//3
printf("%p\n", pi);//4
printf("%p\n", pi+1);//5
system("pause");
return 0;
}
這裏一共打印了五個變量,1、2、4不做過多解釋,我們看到3和5都出現了指針+1,不同的是,3裏pc指向的變量類型是char 類型,所以pc+1只+一個字節。而5裏pi指向的變量類型是int 型,所以pi+1就+4個字節。
打印結果如下:
指針±指針
代表兩個指針之間所經歷的的元素個數
舉一個例子:
int my_point(int a[10])
{
int *p=&a[0];
int *q=&a[9];
retunr q-p;
}
很明顯,這裏指針p指向的是下標爲0的第一個元素,q指向下標爲9的第十個元素,所以q-p就是指針q和指針p之間所經歷8的元素個數,爲9.
同樣,指針之間的運算還可以用來求字符串長度:
int my_strlen(char *a)
{
char *p = a;
while (*p != '\0')
{
p++;
}
return p-a;
}
二級指針
前面我們談及的都是一級指針,我們知道指針變量也是變量,是變量就有地址,就可以被存放,二級指針就是用來存放指針的地址。
如上圖所示,a的地址存放在pa中,pa的地址存放在ppa中,ppa就是一個二級指針。
二級指針解引用
*ppa就是訪問pa。
int b=20;
*ppa=&b;//等價於 pa=&b
**ppa=30;
//等價於*pa=30;
//等價於a=30;
指針和數組
指針和數組本身是沒有聯繫的。
數組名的概念
我們先看一段代碼。
#include<stdio.h>
#include<stdlib.h>
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
printf("%p\n", arr);
printf("%p\n", &arr[0]);
system("pause");
return 0;
}
由此可見,數組名和數組首元素的地址是一樣的。數組名錶示的就是數組首元素的地址。
那麼再看下一段代碼:
int arr[20]={1,2,3,4,5,6,7,8,9,0};
int *p=arr;
在這裏p存放的是首元素的地址。那麼我們可以使用指針來訪問一個數組。
#include<stdio.h>
#include<stdlib.h>
int main()
{
int arr[] = { 1,2,3,4,5,6,7,8,9,0 };
int *p = arr;
int sz = sizeof(arr) / sizeof(arr[0]);
int i = 0;
for (i = 0; i < sz; i++)
{
printf("&arr[%d]=%p p+%d=%p\n", i, &arr[i], i, p + i);
}
system("pause");
return 0;
}
很明顯,&arr[i]和p+i結果是一樣的。所以p+i其實計算的是數組的arr下標爲i的地址。
那麼我們現在直接通過指針來訪問數組:
#include<stdio.h>
#include<stdlib.h>
int main()
{
int arr[] = { 1,2,3,4,5,6,7,8,9,0 };
int *p = arr;
int sz = sizeof(arr) / sizeof(arr[0]);
int i = 0;
for (i = 0; i < sz; i++)
{
printf(" %d", *(p + i));
}
system("pause");
return 0;
}
沒有懸念,打印效果如下:
總結
指針也是一個變量,只不過和其他變量不同的原因是:其他變量放值,指針放地址。所以我們不要害怕指針,就和所有的變量一樣處理就可以了。