一、指针变量
1.1代码分析
先把代码贴上来进行分析。
笔者在写代码时候会加上头文件stdlib
和代码system("pause");
这是为了防止闪屏,在学校时候老师有教过其他写法,但是还是觉得笔者这样写比较容易记得住。
#include<stdio.h>
#include<stdlib.h>
int main() {
int var = 20;
int *p; //定义指针变量
p = &var; //把存储var变量的地址赋值给指针*p
printf("Address of var is :%p\n", &var);
printf("Address stores in p:%p\n", p);
printf("Value of var is :%d\n", *p);
int x = 30;
int *pInt = &x;
printf("%d\n", pInt);
printf("%d\n", (pInt + 1));
system("pause");
return 0;
}
1.2使用指针时候,会频繁进行如下操作:
(1)定义指针变量, (2)把存储刚刚定义的变量如var=20的地址,赋值给指针变量, (3)访问指针变量中可用的地址的值。 指针变量定义形式:数据类型 指针变量名称,比如上面的int p。 指针变量的使用:如 *p=&a**,通过取地址符&,获取 a 的地址,赋值给指针变量。 通过指针来获取地址中存储的内容:在打印中直接使用 *p。
1.3指针与整数的加减运算:
指针变量的自增自减运算。指针加 1 或减 1 运算,表示指针向前或向后移动一个单元(不同类型的指针,单元长度不同)。这个在数组中非常常用。 指针变量加上或减去一个整形数。和第一条类似,具体加几就是向前移动几个单元,减几就是向后移动几个单元。
输出的结果如图:
这里要说一点就是,printf打印的时候,%x和%p,%d都可以打印出来内存地址,但是%x会把地址开头的一串0去掉,%p不会,而%d则是为了方便直观的观察指针指向地址的变化。
二、一级指针和一维、二维数组
2.1.1代码分析
#include<stdio.h>
#include<stdlib.h>
int main() {
//One-Dimensional ArrayList Method-One
int arr[] = { 1,2,3,4,5,6,7 };
int *pInt = arr;
for (int i = 0; i < 7; i++) {
printf("%d=%d\t", arr[i], *(pInt + i));
}
printf("\n");
//Method-Two
for (int i = 0; i < 7; i++) {
printf("%d\t", pInt[i]);
}
printf("\n\n");
//Two-Dimensional ArrayList Method-One
int SecArr[3][3] = { 1,2,3,4,5,6,7,8,9 };
int(*pSec)[3] = SecArr;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
printf("%d\t", *(*(pSec + i)+j));
}
printf("\n");
}
printf("\n");
//Method-Two
int SecArrayList[3][3] = { 1,2,3,4,5,6,7,8,9 };
int(*pSecArr)[3] = SecArrayList;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
printf("%d\t", *(pSecArr[i] + j));
}
printf("\n");
}
system("pause");
return 0;
}
首先我们定义一个长度为7的一维数组,分别存放整数从1到7,数组的首地址,即为数组名arr。定义一个一级指针为pInt且将数组首地址赋值给指针变量pInt。如下图所示。 数组其实是一段内存。如图,指针pInt指向的地址为数组的首地址,然后,我们就进行循环遍历了。这里用了两种方法。 第一种如One-Dimensional Method-One中所写,因为已经对指针变量进行赋值操作,可以从首地址开始,对指针进行移动,从元素1移动元素2,随着每次循环,再移动到3这样,然后再移动。 第二种方法,如One-Dimensional Method-Two所写,因为指针变量可以这里当做数组名使用,直接用pInt[i]作为arr[i]来使用。
二维数组
如上面代码中 //Two-Dimensional ArrayList Method-One
部分。道理如上面的一维数组如出一辙,定义二维数组,定义指针变量,因为一维数组有int *pInt = arr;
二维数组时候也成立,因此pSec[3] = SecArr[3][3]
,那么,int(*pSec)[3] = SecArr;
就容易理解了。在循环遍历时候如上图,记住一维数组可以理解成为一行字,二维数组就是一页字,同理三维数组就是一书。这样比喻,会更加容易理解。类似的,*(*(pSec + i)+j)
可以把*(pSec + i)
看做整体。*(pSecArr[i] + j)
可以把pSecArr[i]
看做整体。