此筆記由個人整理
塞上蒼鷹_fly
課程來自:尚觀C語言
一、指針基礎知識
變量與地址的關係
- 變量名:是用戶對某一個內存空間的抽象表示
- 地址:固定不變的值,不會因爲變量名的改變而改變。等價於指針
指針與指針變量
- 指針:具有指向作用的地址就是指針,地址是常量
- 指針變量:能夠保存地址的變量就是指針變量,指針變量是可以被改變的
直接訪問與間接訪問
-
直接訪問:直接通過地址值訪問得到此地址存放的內容
-
間接訪問:通過指針變量所存放的地址值訪問的到此地址存放的內容
-
不管你的指針是什麼類型,是幾級指針,在相同的編譯環境中,所佔的內存空間都是一致的。
-
案例
#include "stdio.h"
#include "stdlib.h"
int main()
{
int i = 1;
int *p = &i;
printf("i = %d\n",i);
printf("&i = %p\n",&i);
printf("p = %p\n",p);
printf("&p = %p\n",&p);
printf("*p = %d\n",*p);
exit(0);
}
- 結果
空指針與野指針
- 空指針:一開始不知道這個指針要具體存放啥時,就先將其設爲空指針
- 野指針:當前這個指針所指向的空間是不確定的,但還要直接使用
#include "stdio.h"
#include "stdlib.h"
int main()
{
int *p = NULL;//空指針
int *q;//野指針
exit(0);
}
空類型
-
在不確定類型時使用
-
任何類型的值都可以把值賦給空類型指針,空類型指針也可以將內容賦給任何類型的指針
void *q;
二、定義與初始化的書寫
一級指針
定義
- 類型 *變量名
int *p;
初始化
- 類型 *變量名 = 值
int *p = 123;
二級指針
定義
- 類型 **變量名
int **q;
初始化
- 類型 **變量名 = 一級指針取地址
int *p = &i;
int **q = &p;//二級指針
指針運算
- &(取地址)
- *(取值)
- 關係運算(地址值大小相比較)
- 案例
#include "stdio.h"
#include "stdlib.h"
int main()
{
int a[6] = {5,1,7,3,8,3};
int y;
int *p = &a[1];
y = (*--p)++;//在p地址的基礎上地址自減一個元素,所以y的值爲a[0]=5
//在執行完取值的操作後,a[0]所存放的值自增1
printf("y = %d\n",y);
printf("a[0] = %d\n",a[0]);
exit(0);
}
- 結果
三、指針與數組的關係
指針與一維數組
a[i]:a[i] = *(a+i) = *(p+i) = p[i]
&a[i]:&a[i] = a+i = p+i = &p[i]
- 案例1
#include "stdio.h"
#include "stdlib.h"
int main()
{
int a[3] = {1,2,3};
int i;
int *p = a;
for(i = 0;i < 3;i++)
{
printf("%p-->%d\n",a+i,a[i]);
printf("%p-->%d\n",p+i,a[i]);
printf("%p-->%d\n",p+i,*(p+i));
}
printf("/n");
exit(0);
}
- 結果
- 案例2
#include "stdio.h"
#include "stdlib.h"
int main()
{
int a[3];
int i;
int *p = a;
for(i = 0;i < sizeof(a)/sizeof(*a);i++)
printf("%p-->%d\n",&a[i],a[i]);
for(i = 0;i < sizeof(a)/sizeof(*a);i++)
scanf("%d",p++);
//scanf("%d",&a[i]);
//scanf("%d",&p[i]);
p = a;//將自增完的地址重新賦值
for(i = 0;i < sizeof(a)/sizeof(*a);i++,p++)
printf("%p-->%d\n",p,*p);
printf("/n");
exit(0);
}
- 結果
指針與二維數組
- 案例1
#include "stdio.h"
#include "stdlib.h"
int main()
{
int a[2][3] = {1,2,3,4,5,6};
int i,j;
int *p;
p = &a[0][0];
printf("a --> %p\n",a);
printf("a+1 --> %p\n",a+1);//a+1:地址增加一個行元素
printf("p --> %p\n",p);
printf("p+1 --> %p\n",p+1);//p+1:地址增加一個元素
printf("\n");
for(i = 0;i < 6;i++)
printf("%d ",p[i]);
printf("\n");
for(i = 0;i < 2;i++)
{
for(j = 0;j < 3;j++)
{
printf("%p --> %d\n",*(a+i)+j,*(*(a+i)+j));
//printf("%p --> %d\n",&a[i][j],a[i][j]);
}
printf("\n");
}
exit(0);
}
- 結果
指針與字符數組
- 案例1
#include "stdio.h"
#include "stdlib.h"
int main()
{
char str[] = "I love china!";
char *p = str+7;
puts(str);
puts(p);
exit(0);
}
- 結果
- 案例2
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
int main()
{
char str1[] = "hello";
char *str2 = "hello";
printf("str1:%d %d\n",sizeof(str1),strlen(str1));
printf("str2:%d %d\n",sizeof(str2),strlen(str2));
strcpy(str1,"world");
str2 = "world";
puts(str1);
printf("\n");
puts(str2);
printf("\n");
exit(0);
}
- 結果
四、const與指針
- 可以將變量轉換爲常量,不會因爲後面的運算而改變(用指針間接訪問的方法可以改變,但丟失限制)
- 先看到const則爲常量指針,先看到*則爲指針常量
- const後加*p(p地址存放的具體值)–>用來保護這個值不被改變
- *const後加p(p爲存放值的地址) -->用來保護這個地址不被改變
#include "stdio.h"
#include "stdlib.h"
int main()
{
const float pi = 3.14;
float *p = π
*p = 3.14159;
printf("%f",pi);
exit(0);
}
- 結果
- 案例1
const int a;
int const a;
const int *p;
int const *p;//常量指針
int *const p;//指針常量
const int *const p;//即是常量指針又是指針常量
#define PI 3.14
2 * PI * r;
const float pi = 3.14;
2 * pi * r;
常量指針
- 指針的指向可以發生變化,但指向的值不能變化
#include "stdio.h"
#include "stdlib.h"
int main()
{
int i = 1;
int j = 100;
const int *p = &i;
printf("before-->%d\n",*p);
//i = 10;//可以修改
//*p = 10;//報錯:向只讀位置“*p”賦值
p = &j;
printf("after-->%d\n",*p);
}//值不能變但指向可以變
- 報錯
- 結果
指針常量
- 指針的指向不能變化,但指向的值可以變化
#include "stdio.h"
#include "stdlib.h"
int main()
{
int i = 1;
int j = 100;
int *const p = &i;
printf("defore-->%d\n",*p);
i = 100;
printf("after-->%d\n",*p);
//p = &j;//報錯:向只讀位置“p”賦值
}
- 報錯
- 結果
即是常量指針又是指針常量
- 指針的指向不能被改變,指向地址存放的值也不能被改變
#include "stdio.h"
#include "stdlib.h"
int main()
{
int i = 1;
int j = 100;
const int *const p = &i;
printf("before-->%d\n",*p);
*p = 10;//報錯:向只讀位置“*p”賦值
p = &j;//報錯:向只讀位置“p”賦值
}
- 報錯
五、指針數組與數組指針
數組指針
定義
- 指向數組的指針
格式
- [存儲類型] 數據類型 (*指針名) [下標] = 值
int (*p)[3]; --> int[3] *p;
- 案例
#include "stdio.h"
#include "stdlib.h"
int main()
{
int a[2][3] = {1,2,3,4,5,6};
int i,j;
int *p = *a;
int (*q)[3] = a;
for(i = 0;i < 2;i++)
{
for(j = 0;j < 3;j++)
{
printf("%p --> %d\n",*(a+i)+j,*(*(a+i)+j));
//printf("%p --> %d\n",*(q+i)+j,*(*(q+i)+j));
//printf("%p --> %d\n",&a[i][j],a[i][j]);
}
printf("\n");
}
printf("%p %p\n",a,a+1);
printf("%p %p\n",q,q+1);
exit(0);
}
- 結果
指針數組
定義
- 存放指針的數組
格式
- [存儲類型] 數據類型 * 數組名 [長度]
int *arr[3]; --> int *[3] arr;
- 案例
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
int main()
{
int i,j,k;
char *tmp;
char *name[5] = {"Fllow me","Basic","Great","Fortran","Computer"};
for(i = 0;i < 4;i++)
{
k = i;
for(j = i+1;j < 5;j++)
{
if(strcmp(name[k],name[j]) > 0)
k = j;
}
if(k != i)
{
tmp = name[i];
name[i] = name[k];
name[k] = tmp;
}
}
for(i = 0;i < 5;i++)
puts(name[i]);
exit(0);
}
- 結果