一、指针概述
1.简介
指针:其实就是地址。
指针变量:用来存储变量地址的变量。
2.初始化
1)先定义后初始化
int a =10;
int *p;
p=&a;
2)定义并初始化
int a=10;
int *p =&a;
备注:在数据类型后,变量名称前的”*“是一个说明符,用来说明该变量是一个指针变量。
如果前面没有数据类型,如:*p,这里的”*“是一个指针运算符,用来取出指针变量所指向的变量。
3.指针变量的占用内存
在同一编译器环境下,所占用的内存是固定的,与指针变量的类型无关。
不同的编译器,指针变量的占用内存不同。
16位编译器->2字节,32位编译器->4字节 ,64位编译器->8字节
二、指针与数组
1.p是指针,a是数组
1)如果p指向了一个数组元素,则p+1始终表示指向数组该元素的下一个元素。与编译器环境无关、与指向的数据类型无关。
例如:p=&a[2], p+1=&a[3]
2)对于不同类型的数组元素,p值的改变是不同的。如果数组元素为int型,p+1代表p的值加上2(在16位编译器环境下),不管p+1的值是多少,它始终保证刚好指向下一个元素。
2.假设p的初始值是&a[0],那么:
1)p+i和a+i,都可以表示元素a[i]的地址。它们都指向数组第i个元素的地址。
2)*(p+i)和*(a+i),都表示数组元素a[i].
3)虽然p+i和a+i都指向数组的第i个元素,但是二者还是有区别的。作为指针变量的p是可以改变自身的值,如p++。但是a是一个代表数组首地址的常量,同时也是一个数组的名字,它的值是不能改变的,即a++不合法。
3.用数组名作为函数实参时,实际上是把数组的首地址传递给形参数组,两个数组公用同一段内存空间。
4.在很多情况下,指针和数组是可以相互切换使用的,但并不能说指针就是数组。
5.例子
#include
#include
int main() {
// 定义一个int类型的数组
int a[4] = {1, 2, 3, 4};
// 定义一个int类型的指针,并指向数组的第0个元素
int *p = a;
int i;
for (i = 0; i < 4; i++) {
// 利用指针运算符*取出数组元素的值
int value = *(p+i);
printf("a[%d] = %d \n", i, value);
}
return 0;
}
三、指针与字符串
1.字符串可以看做一个特殊的字符数组,自然也就是一个数组。之所以特殊,是因为,它会在数组的末尾自动添加"\0",表示结尾。
2.指针和字符串的使用
#include
int main() {
char a[10]="china";
char b[10];
//b="china";//因为b是数组的首地址,是一个常量,不能进行赋值运算
char *c="china";
char *d;
d="china";//先声明,再初始化
char *e="china";//e是一个指针变量,初始化的时候指向china
e="uk";//指针指向uk,修改了指针的地址
//*e='m';//因为e指向的是一个常量,是不能修改的
int leng =strlen(e);
printf("%d\n",leng);//长度:2
printf("%c\n",*e);//这里的e指向的是字符串的第一个字符。
//printf("%s\n",*e);//因为e指向的是uk的首字符“u”,不能以字符串形式输出。
return 0;
}
3.遍历字符串
char a[]="china";
char *p=a;
for(;*p !='\0';p++){
printf("%c",*p);
}
//输出结果:china
四、指针与函数
1.回顾一下
int *p=12;
p存储的是地址。
*p是取出内存地址的值。
p+1,下一个地址
*(p+1),下一个地址的值
2.返回指针的函数
char * upper(char *str) {
// 先保留最初的地址。因为等会str指向的位置会变来变去的。
char *dest = str;
// 如果还不是空字符
while (*str != '\0') {
// 如果是小写字母
if (*str >= 'a' && *str <= 'z') {
// 变为大写字母。小写和大写字母的ASCII值有个固定的差值
*str -= 'a' - 'A';//a-97 A-65
}
// 遍历下一个字符
str++;//下一个地址
}
// 返回字符串
return dest;
}
3.指向函数的指针
为什么指针可以指向函数?
函数作为一段程序,在内存中也要占据部分存储空间,他也有一个起始地址,即函数的入口地址。既然函数有地址,指针变量就是用来存储地址的,因此,指针可以指向一个函数,函数名就是函数的地址。
4.例子
1)声明和初始化
#include
#include
int sum(int a, int b) {
return a + b;
}
int main() {
//int (*p)()=sum;//声明并初始化指针
int (*p)(int, int)=sum;//建议使用这种
//int (*p)(int number1,int number2)=sum;
//int result = (*p)(1, 3);//用指针调用函数
int result=p(1,3);
printf("%d\n", result);
return 0;
}
2)实际应用
#include
#include
#include
// 减法运算
int minus(int a, int b) {
return a - b;
}
// 加法运算
int sum(int a, int b) {
return a + b;
}
//乘法运算
int mul(int a, int b) {
return a * b;
}
// 这个counting函数是用来做a和b之间的计算,至于做加法还是减法运算,由函数的第1个参数决定
void counting(int (*p)(int, int), int a, int b) {
int result = p(a, b);
printf("计算结果为:%d\n", result);
}
int main() {
// 进行加法运算
counting(sum, 6, 4);//传入指针变量的名字p
// 进行减法运算
counting(minus, 6, 4);
// 进行乘法运算
counting(mul, 6, 4);
return 0;
}