学习之第一周小结 指针
1、什么是指针
指针:一个变量的地址称为该变量的指针。
指针变量:用来存放一个变量的地址的变量称为指针变量。但常把指针变量简称为指针。
2、指针的用法
初始化:int n;
int *p = &n;//指针p被初始化,&为取址符,表明p的初值为n的地址&n。
赋值:int *q;
q = &n;//指针q被赋值,q的初值为&n,则*q等于n;符号*为指针运算符。
3、&和*的关系
若p = &a,则&*p = p;*&p = p;//可见&和*在一起,抵消彼此作用。
4、指针引用时需要注意点:
1)指针变量是用来存放地址的,不要给指针变量赋常量。
//错误写法:int *p; p = 1000;
2)指针变量没有指向确定的地址前,不要对他所指向的对象赋值
错误写法:int *p, a = 5; *p = 5;
纠正:int *p, b; p = &b; *p = 5;//表明p指向的变量b = 5;
5、指针变量作为函数参数
在C语言中,当指针变量作为函数参数,其作用是将一个变量地址传送到另一个函数。此时形参从实参获得了变量的地址,也就是说实参和形参指向同一个变量,当形参指向的变量发生变化时,实参指向的变量也随之变化。
//例如:将两个数由大到小顺序输出
#include <stdio.h>
void swap(int *p1, int *p2)
{
int p = *p1;
*p1 = *p2;
*p2 = p;
}
int main()
{
int a = 3, b = 4;
int *prt1, *ptr2;
ptr1 = &a; ptr2 = &b;
if(a<b) swap(ptr1,prt2);
printf("%d,%d\n",a,b);//输出4,3
return 0;
}
但如果上面的例子改变的不是指针形参指向的变量的值,而是改变了指针形参的值,则效果是不一样的。
//例如将上面的swap函数换成如下:则输出a和b的值不变
void swap(int *p1, int *p2)
{
int *p = p1;
p1 = p2;
p2 = p;
}
6、指向函数的指针
函数作为一段程序,在内存中也要占据一片存储区域,它有一个起始地址,即函数的入口地址,这个地址称为函数的指针。可以定义一个指针变量指向函数,然后通过指针调用函数,一般形式如下:类型名(*指针变量名)();
例如:int(*p)()
C语言规定函数名就是函数的入口地址。所以当指向函数的指针变量等于一个函数名时,表示该指针变量指向函数。此时可以通过指向函数的指针调用该函数。形式为:(*指针变量名)(实参表)
指向函数的指针变量主要有两个用途:
1)调用函数
2)将函数作为参数在函数间传递
//例如:求两个数中较大的数
#include <stdio.h>
int max(int x, int y)
{
int z = (x>y)?x:y;
return z;
}
void main()
{
int a,b,c;
int(*p)();
p = max;
scanf("%d,%d",&a,&b);
c = (*p)(a,b);//调用max函数
printf("%d,%d,max is %d\n",a,b,c);
}
8、返回值为指针的函数
返回值为指针的函数形式:类型名 *函数名 (参数表)
例如:int *max(int *x, int *y)//返回值为整型指针的函数
{
int *q;
q = (*x > *y) ? x : y;
return q;
}
9、指针与数组
1)指向数组元素的指针变量
例如:int a[5], *p;
int *p = a;
int *p = &a[0]
//上面两句等价;并且有p+i和a[i]都表示a[i]的地址;
//*(p+i)和*(a+i)表示p+i和a+i所指向的数组元素a[i]的值
//由此可见,引用一个数组元素有两种方法:下标发:a[i]和指针法:*(a+i)
2)数组和指针不等价
考虑如下两个声明:
int a[3];
int *b;
声明一个数组时,编译器将根据声明所指定的元素数量为数组保留内存空间,然后在创建数组名,它的值是一个常量,指向这段空间的起始地址。声明一个指针变量时,编译器只为指针本身保留内存空间,指针变量并未被初始化为任何现有的内存空间。因此,上述声明后,表达式*a合法,而表达式*b确实非法的。*b将访问内存中某个不确定的位置,或者导致程序终止。另一方面,表达式b++可以通过编译,但a++却不行,因为a的值是一个常量。故指向数组元素的指针可以自增和自减,方便了数组元素的操纵。
3)指针和多维数组
在了解指正和多维数组的关系前,首先了解多维数组的特性:(1)C语言把二维数组看做是一维数组的集合,即二维数组是一个元素为一维数组的一维数组;(2)不带任何下标的二维数组名表示二维数组的起始地址,进行加法操作时则表示作为其他元素的一个一维数组(即二维数组的一行)的起始地址;(3)只带一维下标的二维数组名表示作为其元素的一个一位数组(即二维数组的一行)的起始地址,对其进行加法操作时表示该一维数组(即二维数组的一行)的一个元素地址。
例如:int a[2][3], (*p)[3], *q;
p = a; //此时p+1等同于a+1,指向包含3个元素的一维数组a[1],所以*(p+1)等于一维数
//组名a[1],*(P+1)+1等于a[1]+1,所以*(*(p+1)+1)=a[1][1];
q = a[0];//q、a[0]、&a[0][0]相同,P+1等于a[0]+1,都指向a[0][1],即*(p+1)=a[0][1];
10、指针与字符串
字符串以数组形式存储,故字符串的本质是一维数组,指针和数组的原则适用于指针和字符串。
例如:char *str = "hello";char *str; str = "hello"//与上面的表达式等价
一个字符指针变量只能指向一个字符数据,不能同时指向多个字符数据,更不能把字符串全部放在指针变量中。因此如下形式不合法:char *str="hello"; *str = "china"
11、指针数组
C语言规定如果一个数组的元素都是指针类型,则称之为指针数组。
指针数组定义的形式为:类型名 *数组名[常量表达式]
例如:int a[5];//表示指针数组a中每个元素都是指向int型变量的指针变量。
12、指向指针的指针
一般形式:类型名: **指针变量名
例如 int **p, *a, b;
a = &b;
p = &a;//则有p = &&b; *p = a; **p = b;
13、指向结构变量的指针变量
一般形式:struct 结构体名 *p
对结构体变量的成员的引用:(1)结构体变量名.成员(2)(*结构体变量名).成员
(3)指针变量->成员名