一.需要掌握的知识点
指针和指针变量的含义
C语言的数据类型:1.基本类型(整数,浮点数)2.构造类型(数组)3.内存地址
一个变量定义成功的意思是在计算机内存中获得一块存储区,这个存储区的大小由数据类型决定
其实指针是一个无符号的整数,但是又不能把这个整数直接赋值给指针变量,值得一提的是,指针指向的是都是首地址(无论对于数组还是对于整数,浮点数等)
指针的存放和声明,初始化和引用
指针的定义:例如基类型是整型的指针——
int *p()
int (*p)[4]:基类型是列的指针
(注意:取地址运算符&和取值运算符*的优先级为2,()[]等符号的优先级为1,但定义时 的*只是一个标识符,修饰符)
指针的初始化
指针必须初始化(最好通过初始化操作来为指针赋值)才能为指向的变量赋值,例如
int *p,a;
scanf("%d",p)就是错的,应该初始化 int *p=&a;
指针的引用
&取地址运算符,*取值运算符
注意:机器只会分配两个或者更多字节单元来存放指针的地址值
指针与函数
(1).指针作为函数的参数
指针作为函数的参数,注意:形参还是被另外分配了储存单元,这也解释了为什么下面的第二串代码没有起到相应的作用,但是可以通过间接访问来对相应的变量操作,
指针作为函数参数的时候,函数内部涉及到的间接访问都会被保存
swap(int *p1,int *p2)
{
int t;
t=*p1;
*p1=*p2;
*p2=t;
}这样的话就可以成功交换,但是如果是
int *t
t=p1;p1=p2;p2=t;
就不可以达到交换的效果
(2)指针指向函数
定义的时候int(*p)(int ,int)
int process(int x,int y,int(*f)(int int ))//这个地方的第三个形参就是一个指向函数的指针
{
return *f(x,y)
}
(3)函数的返回值是指针类型
定义的时候int *p(int x,int y)(x,y可以省去)
指向数组的指针
(1)指向一维数组的定义,初始化,引用元素的方式(*(p+1)或者p[i])
(2)利用指针访问数组:1.下标2.指针运算符3.利用指针的自加自减
(3)指向二维数组的定义,初始化,int **p或者int (*p)[4];
引用元素的方式,例如要表示a[1][1]
全部取值表示:*(*(p+1)+1)
利用下标表示:*(p[1]+1)
关键记住p[1]就是*(p+1)
指向字符串的指针
最重要的就是赋值,对于字符串来说赋值需要strcpy但是对于指向字符串的指针直接赋值即可
指针与数组的差别:
存储:数组是一段储存区,但是指针被分配存放值的字节,并且指向基类型的第一个元素
赋值
定义:指针必须要初始化,才能赋值或者输入
运算上,数组名是变量,是不可以进行自加自减的
存放指针的数组
char*p[4],表示定义了包含四个指针的数组,
用法举例
char *p[2]={"hello","china"};
二.易错问题
1.如果有char *p;char a[]="hello";p=a;
注意a数组长度不同于p所指的字符串长度(区别在于'\0')
如果要对a进行自增运算,那么char(*a)[3]是不行的,虽然他是一个数组但是无连续存储区,所以必须要初始化
如果有二维数组int w[3][5],那么*(*w+3)表示的是w[0][3],*(w+1)[4]表示的是*((w+1)[4])如果要表达正确那么需要(*(w+1))[4],或者是*(w[1]+4)一定注意,还有就是w+1表示的是w[1]的地址,必须还要加一个*才能对它的列进行操作
读程序题一定要注意下标
学习通上的错题
请判断以下的输出结果:4,3,3
#include <stdio.h>
void sp(int *a)
{
int b=2;
a=&b; *a=*a*2;
printf("%d,",*a);
}
int main()
{
int k=3,*p=&k;
sp(p);
printf("%d,%d\n",k,*p);
return 0;
}
这道题就很好的证明了之前传地址给形参,形参依旧是被重新分配内存的猜想,sp函数中对*a的值进行了重新赋值,只是对*a进行操作,最后*a不会被保留
2.自加自减运算符和取值运算符的优先级一样,但是结合方式都是从右到左,因此如果出现*p++,(意思是先对p进行取值操作,然后再将p+1,)或者*++p那么就是p先自加然后再取值,最后导致的结构都是p不再指向原来的数
3.指针的初始化不要想的太死板,char *p="hello"也是初始化,注意:对于数组的初始化可以加{},但是指针不行