一、指针是什么?
要知道什么是指针,先来了解下指针的存储和读取。
当我们在对程序编译时,会为变量分配存储单元。如我们定义int a=10;就是为a这个整型变量分配了4个字节。内存区的每一个字节都有一个编号,这就是“地址”,相当于旅馆中的房间号。在里面存数据就相当于在这个房间中住旅客了。
由于通过地址能找到变量单元,所以我们说地址指向这个变量单元。
二、指针的定义和使用
1、小例子看指针
int a = 10;————>定义了一个整型变量,并赋值为10;
int *p;——————>定义了一个指针,这里的*仅仅表示p一个指针,没有其他任何含义;
p=&a;——————>我们把p指针指向了a,也表示把a的地址给了p;
printf(“a=%i\t;p=%p\t;p指向的值是:%d\n”,a,p,*p);———>我们分别打印a的值,p的地址值,p指向的地址里面的内容。
可以看出,当我们把p指向a时,我们可以说a和*p代表的是同一个东西。
所以指针的定义格式为:数据类型 *指针变量名
这里介绍两个符号 :
(1)& 取地址运算符。&a是变量a的地址。
(2)* 指针运算符(或叫“间接访问”运算符),*p代表指针变量p指向的对象。
2、变量访问方式
①直接访问 :通过变量名或地址访问变量的存储区。
②间接访问:将一个变量的地址存放在另一个变量中。如:将变量 a 的地址存放在变量p 中, 访问a 时先找到p,再由p 中存放的地址找到 a。
3、注意:
(1) 在变量定义时,* 号表示该变量是指针变量。
(2)定义指针变量后,系统为其分配存储空间, 用以存放其他变量的地址, 但在对指针变量赋值前,它并没有确定的值,也不指向一个确定的变量。
(3)p与*p不同,p是指针变量, p的值是p所指向的变量的地址。 *p 是p 所指向的变量 ,*p的值是p所指向的变量的值。
(4)引用指针变量时的 * 与定义指针变量时的 * 不同的。定义变量时的 * 只是表示其后的变量是指针变量。
4、简单的指针运算
我的错误:
int a=2,b=5,c,d,*p;
(1) p=&a;
(*p)++;———>等价于a++;
P的值是a的地址,*p的值是2,p的值不变,完后*p的值加1变为3。
(2) c=*p++;———>等价于c=*(p++);
执行后c的值为3,*p的值为5。
(3) d=*++p;———>d*(++p);
执行后d为3,*p为3。
注意:上面这是错的,为什么我也要写出来呢?因为这是很容易忽视的问题,那就是顺序存储。我们自认为我们的指针能一级往下找,其实不是这样的,通过下图就明白 了。
这与我们预料的完全不一样,从这里可以看出P++其实是加了一int的长度,即把指针往后挪4个字节。
4、下面求2个数的大小的程序,我们可以看出,指针也有类似于“单向值传递”的规律。
int *p1,*p2,*p,a,b,max,min;
scanf("%d %d",&a,&b);
p1=&a;
p2=&b;
if (a<b)
{
p=p1;
p1=p2;
p2=p;
}
printf("a=%d,b=%d\n",a,b);
printf("max=%d,min=%d\n",*p1,*p2);
这儿知道只是指针变换了一下,等于把门牌号换了一下,但是旅客并没有变。
三、指针和函数
(1)指针变量做为函数参数
void test1(int num1,int num2)
{
//单向值传递,不改变实参a,b的值
int temp;
temp = num1;
num1 = num2;
num2 = temp;
}
void test2(int *p1,int *p2)
{
//交换了p1,p2变量的值,所以a和b的位置也会换掉
int temp;
temp = *p1;
*p1 = *p2;
*p2 = temp;
}
void test3(int *p1,int *p2)
{
//只是挪了指针,但是变量的值还是没有变,等于换门牌号(指针指的位置变化)
int *temp;
temp=p1;
p1=p2;
p2=temp;
}
int main()
{ int a,b,*ptr1,*ptr2;
printf("输入两个数比较:\n");
scanf("%d%d",&a,&b);
printf("原 值:\t a = %d b = %d\n",a,b);
ptr1 = &a;
ptr2 = &b;
test1(a,b);
//对他们进行分别调用,可以看出其中的差别
printf("调用test1后:a = %d b =%d\n",a,b);
//test2(ptr1,ptr2);
//printf("调用test2后:a = %d b =%d\n",a,b);
//test3(ptr1,ptr2);
//printf("调用test3后:a = %d b =%d\n",a,b);
getchar();
getchar();
//printf("max = %d min =%d",max min);
return 0;
}
#include <stdio.h>
void test1(int num1,int num2)
{
//单向值传递,不改变实参a,b的值
int temp;
temp = num1;
num1 = num2;
num2 = temp;
}
void test2(int *p1,int *p2)
{
//交换了p1,p2变量的值,所以a和b的位置也会换掉
int temp;
temp = *p1;
*p1 = *p2;
*p2 = temp;
}
void test3(int *p1,int *p2)
{
//只是挪了指针,但是变量的值还是没有变,等于换门牌号(指针指的位置变化)
int *temp;
temp=p1;
p1=p2;
p2=temp;
}
int main()
{ int a,b,*ptr1,*ptr2;
printf("输入两个数比较:\n");
scanf("%d %d",&a,&b);
printf("原 值:\t a = %d b = %d\n",a,b);
ptr1 = &a;
ptr2 = &b;
test1(a,b);
printf("调用test1后:a = %d b = %d\n",a,b);
//test2(ptr1,ptr2);
//printf("调用test2后:a = %d b = %d\n",a,b);
//test3(ptr1,ptr2);
//printf("调用test3后:a = %d b = %d\n",a,b);
getchar();
getchar();
//printf("max = %d min =%d",max min);
return 0;
}
解释见函数调用时的注释,挨得近,看得明白
(2)函数返回指针
前面我们用到的函数, 有些无返回值, 有些有返回值,一个函数的返回值也可以是一个指针类型的数据。
定义结构:
数据类型 *函数名(形参表)
{函数体;}
说明:定义一个返回指针值的函数与以前定义函数格式基本类似, 只是在函数名前加 * , 它表明该函数返回一个指针值。
(3)指向函数的指针
函数的指针: 函数的入口地址
在程序执行过程中调用函数时, 计算机会转去执行函数体内的语句, 因此计算机必须知道函数在什么地方。实际上函数在内存中也要占据一片存储单元, 这片存储单元一个起始地址, 我们称其为函数的入口地址,即函数的指针, 这个函数的入口地址是用函数名来表示。
因此我们可以定义一个指针变量, 让它的值等于函数的入口地址, 然后可以通过这个指针变量来调用函数, 该指针变量称为指向函数的指针变量。指针和数组。
1>定义结构:
数据类型 (*函数名)(形参表);
2>说明:
①数据类型: 指针变量所指向的函数的返回值类型
②形参表列: 即指针变量所指向的函数的形参表列
③格式中的小括号不能省略
④因为函数名为函数的入口地址,所以直接将函数名赋给指针变量即可
⑤使用指针变量调用函数格式 : (*指针变量名)( 实参表列)
#include <stdio.h>
int add( int b[ ] , int n);
void main( )
{ int a[6]={ 1, 3, 5, 7, 9, 11},total ;
int (*pt) ( int b[ ] , int n ) ;
pt = add ;
total = (*pt) ( a , 6 ) ;
printf( “total = %d \n” ,total ) ;
}
int add( int b[ ] , int n )
{ int i , sum = 0 ;
for ( i = 0 ; i<n ; i++ )
sum = sum+b[i];
return(sum);
}