一、
前面学过通过变量名访问变量
#include<stdio.h>
int main()
{
int a = 9;
printf("a的值:%d\n",a);
return 0;
}
指针则是通过 存放变量的地址 来访问变量
#include<stdio.h>
int main()
{
int a = 9;
printf("a的值:%d\n",a);
printf("变量a的地址:%p\n",&a);
printf("通过变量a的地址来访问变量a:%d\n\n",*(&a));
return 0;
}
二、不同类型的变量存放不同类型的内容
整型变量 存放整型数
字符型变量 存放字符
指针变量 存放地址
。。。。。。
三、怎样定义一个指针变量
1.定义指针变量并赋值的操作分2中
#include<stdio.h>
int main()
{
int a = 9;
int *p;//定义1个指针
p = &a;//给指针变量赋值
printf("a的值 = %d \n",*p);
return 0;
}
或者
#include<stdio.h>
int main()
{
int a = 9;
int *p = &a;//定义并初始化1个指针
printf("a的值 = %d \n",*p);
return 0;
}
***注意 * 只有在定义1个指针的时候,才是 指针的标识符。
其他时候 * 是1个运算符,作用是 取出地址里的值。
2.用指针访问变量
#include<stdio.h>
int main()
{
int a = 9;
int *pa = &a;
printf("a的值 = %d \n",a);
printf("a的地址 = %p \n",&a);
printf("指针pa的值 (指针就是地址,所以用 百分之p 而不是 百分之d)= %p \n",pa);
printf("通过指针访问a的值a的值 = %d \n",*pa);
return 0;
}
3.不同类型指针,自增后占用的空间也不同
#include<stdio.h>
int main()
{
int *p1 ;//整型指针只能存放整数的地址
char *p2;//字符型指针只能存放字符数据的地址
int a=5;
char c = 'A';
p1 = &a;
p2 = &c;
printf("a=%d,c = %c\n",*p1,*p2);
printf("a的地址:%p,a的地址++: %p\n",p1,p1++);
printf("c的地址:%p,c的地址++: %p\n",p2,p2++);
return 0;
}
可以看到 int型指针自增后,自增4字节
char型指针自增后,自增1字节
四.指针与数组
(1)
#include<stdio.h>
int main()
{
int arr[3] = {1,2,3};
int *parr ;
int i;
parr = arr;
printf("第1个元素的地址:%p\n",&arr[0]);
printf("第2个元素的地址:%p\n",&arr[1]);
printf("第3个元素的地址:%p\n",&arr[2]);
for(i=0;i<sizeof(arr)/sizeof(arr[0]);i++)
{
printf("指针指向数组首地址后依靠自增运算,指针的内容:%p\n",parr);
parr++;
}
return 0;
}
可以发现,依靠指针自增,可以指针滑动的效果,依次指向数组的第0个元素,第1个元素,第2个元素,,,,,,,
(2)指针指向数组后,可以用指针代替数组名,
因为数组名是一个地址,指针也是地址。所以,此时可以用指针代替数组名
指针滑动后要让指针指向最初的位置,否则会越界
#include<stdio.h>
int main()
{
int arr[3] = {1,2,3};
int *parr ;
int i;
parr = arr;
printf("第1个元素的地址:%p\n",&arr[0]);
printf("第2个元素的地址:%p\n",&arr[1]);
printf("第3个元素的地址:%p\n",&arr[2]);
for(i=0;i<sizeof(arr)/sizeof(arr[0]);i++)
{
printf("指针指向数组首地址后依靠自增运算,指针的内容:%p\n",parr);
parr++;
}
printf("\n\n");
parr = arr;//***指针滑动后要让指针指向最初的位置,否则会越界***
for(i=0;i<sizeof(arr)/sizeof(arr[0]);i++)
{
printf("数组的第%d个元素:%d\n",i,parr[i]);
}
return 0;
}
(3)也可以这样访问数组的元素
#include<stdio.h>
int main()
{
int arr[3] = {1,2,3};
int *parr ;
int i;
parr = arr;
printf("第1个元素的地址:%p\n",&arr[0]);
printf("第2个元素的地址:%p\n",&arr[1]);
printf("第3个元素的地址:%p\n",&arr[2]);
for(i=0;i<sizeof(arr)/sizeof(arr[0]);i++)
{
printf("指针指向数组首地址后依靠自增运算,指针的内容:%p\n",parr);
parr++;
}
printf("\n\n");
parr = arr;
for(i=0;i<sizeof(arr)/sizeof(arr[0]);i++)
{
printf("数组的第%d个元素:%d\n",i,*parr);
parr++;
}
return 0;
}
五、指针、数组、函数的综合
实现键盘输入,排序,传递数组,指针访问变量,指针滑动
#include<stdio.h>
int fun(int *p,int n)
{
int i;
int max = 0;
printf("接收到的数组元素分别为:\n");
for(i=0;i<n;i++)
{
printf("%d\n",p[i]);
}
//排序
for(i=0;i<n;i++)
{
if(max<p[i])
max = p[i];
printf("第%d次排序结果:%d\n",i,max);
}
printf("最高分 = %d",max);
}
int main()
{
int score[5];
int i;
int *pscore;
pscore = score;//元素0的地址就是数组的首地址
for(i=0;i<sizeof(score)/sizeof(score[0]);i++)
{
printf("输入第%d个学生的成绩:\n",i);
scanf("%d",pscore);
pscore++;
}
pscore = score;
//调用函数进行分数的排序,找出最高分
fun(pscore,sizeof(score)/sizeof(score[0]));
return 0;
}
注意
当指针指向数组名时,
比如:
int array[5] = {1,2,3,4,5};
int *p;
p = array;
可以在部分场合,用指针代替数组名。
比如
printf(“array[0] = %d”,p[0]);
但是,下面的情况不能:
计算数组有几个元素时,
要用sizeof(array)/sizeof(array[0])
而不能sizeof§/sizeof(p[0])
代码如下:
#include<stdio.h>
int fun(int *p,int n)
{
int i;
int max = 0;
printf("接收到的数组元素分别为:\n");
for(i=0;i<n;i++)
{
printf("%d\n",p[i]);
}
//排序
for(i=0;i<sizeof(p)/sizeof(p[0]);i++)
{
if(max<p[i])
max = p[i];
printf("第%d次排序结果:%d\n",i,max);
}
printf("最高分 = %d",max);
}
int main()
{
int score[5];
int i;
int *pscore;
pscore = score;//元素0的地址就是数组的首地址
for(i=0;i<sizeof(score)/sizeof(score[0]);i++)
{
printf("输入第%d个学生的成绩:\n",i);
scanf("%d",pscore);
pscore++;
}
pscore = score;
//调用函数进行分数的排序,找出最高分
fun(pscore,sizeof(score)/sizeof(score[0]));
return 0;
}
正确的代码也可以写成这样
(核心内容就2点:指针滑动,或者让指针指向数组并用指针代替数组名)
#include<stdio.h>
int fun(int *p,int n)
{
int i;
int max = 0;
printf("接收到的数组元素分别为:\n");
for(i=0;i<n;i++)
{
printf("%d\n",p[i]);
}
//排序
for(i=0;i<n;i++)
{
if(max<*p)
max = *p;
p++;
printf("第%d次排序结果:%d\n",i,max);
}
printf("最高分 = %d",max);
}
int main()
{
int score[5];
int i;
int *pscore;
pscore = score;//元素0的地址就是数组的首地址
for(i=0;i<sizeof(score)/sizeof(score[0]);i++)
{
printf("输入第%d个学生的成绩:\n",i);
scanf("%d",pscore);
pscore++;
}
pscore = score;
//调用函数进行分数的排序,找出最高分
fun(pscore,sizeof(score)/sizeof(score[0]));
return 0;
}
浦东就是上海,上海就是浦东^ _ ^
六、 指针数组
多个整数放在一起,叫整型数组。
多个指针放在一起,叫做指针数组(这几个指针类型是相同的,还要注意:指针变量是用来存放地址的)
#include<stdio.h>
int main()
{
int a=2;
int b=3;
int c=4;
int i;
int arr[3];
int* parr[3];//多个指针叫做指针数组
//接下来的操作是把一些没有关系但是是同一类型的变量的地址存入指针数组里的各个元素中
parr[0] = &a;//指针变量是用来存放地址的
parr[1] = &b;
parr[2] = &c;
for(i=0;i<3;i++)
{
printf("该指针数组里有3个元素,元素%d是地址:%p,该地址里保存的值是:%d\n",i,parr[i],*(parr[i]));//parr[i]是地址,所以*(parr[i])是变量
}
return 0;
}
七、数组指针
数组指针就是一个指针。它是数组的指针。
一般,把数组名传递给数组指针,就可以通过这个数组指针来访问数组。
下面先介绍1个普通指针,不是数组指针
#include<stdio.h>
int main()
{
int a[3]={1,2,3};
int *p;
int i;
p = a;
for(i = 0;i<3;i++)
{
printf("%d\n",*(p++));
}
return 0;
}
这块代码里的指针就是普通指针。
只不过,该指针刚好指向数组的首地址。
接下来的是数组指针
#include<stdio.h>
int main()
{
int a[3]={1,2,3};
int (*p)[3];
int i;
int *p2;
p = &a[0];//这个数组指针是一个指针,所以传给它的是地址。数组指针指向整个数组
//把1个数组的首地址赋值给数组指针。
//要关注的是数组指针的偏移量:p++偏移的是整个数组的大小
//而1个指向数组首地址的普通指针,它的偏移量是一个数组元素的大小
p2 = &a[0];
printf("数组的首地址%p\n",a);
printf("数组的首地址%p\n",&a[0]);
printf("数组的首地址%p\n",p);
printf("数组的第3个元素:%d\n",a[2]);
printf("数组指针偏移1次的地址%p\n",p++);
printf("普通指针偏移1次的地址%p\n",p++);
printf("可以发现数组指针和普通指针最大的区别在于偏移量\n");
printf("有一个疑问!!为什么不能用p[0],p[1],p[2]来访问数组元素????\n");
printf("p[0] = %d\n",p[0]);
printf("p[1] = %d\n",p[1]);
printf("p[2] = %d\n",p[2]);
return 0;
}
现在还不明白,听说二维数组里能详细了解数组指针。
八、函数指针
函数指针是一个指针变量,存放的是函数的地址。
问题:如何定义?如何通过它来访问函数?
注意:函数指针的格式要求比较强:有参数类型,个数,返回值的要求
函数名就是函数的地址
接下来的是不在意细节的函数指针
#include<stdio.h>
void fun()
{
printf("你好\n");
}
int main()
{
void (*p)();
p = fun;
p();
return 0;
}
#include<stdio.h>
void fun()
{
printf("你好\n");
}
int main()
{
void (*p)();
p = fun;
(*p)();
return 0;
}
接下来是在意细节的函数指针
#include<stdio.h>
int fun(int a,int b)
{
return a+b;
}
int main()
{
int (*p)(int a,int b);
int ret;
p = fun;
ret = (*p)(2,3);
printf("ret = %d",ret);
return 0;
}
复杂点的回调函数应用
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//1-结构体模板
struct student
{
int num;
char *name;
};
//2-定义结构体变量
struct student myST={0x01,"FTMS"};
//3-功能函数
void fun(struct student *p_event)
{
printf("num:%x,name:%s\r\n",p_event->num,p_event->name);
}
//4-回调函数
void handle(void fun(struct student *p_event))
{
fun(&myST);
}
int main()
{
handle(fun);
return 0;
}