从零开始学编程---第一步-C语言(二十一)

时间:2014-03-08 22:40    点击:

话说了一大堆,接下来让我们定义一个指针
定义一个年龄的指针
int* page; 这就是定义了一个指针,和定义普通变量就多了一个*符号而已
*号必须放在类型和指针变量中间,摆在哪里无所谓
这样也是可以的 int *page;   
*号是取值运算符,这里不是乘号的意思
为什么变量名用了p开头,引用英文pointer,这里表示它是一个指针,而非普通变量,加不加p都无所谓的
指针变量是page,他只存放变量的地址,之前的*号是取值用的,等会就说
如果不加*号,那就等于定义了一个普通变量,而非指针变量
竟然是变量,那说明page里存放的地址是可以存放别的地址的
*page   这不是指针变量,*不是指针变量的一部分

假设我们定义
int age=19;
int *page=&age;

定义了一个普通变量又定义了一个指针
&是取地址符,这个大家都用过了,scanf经常用的
&age表示变量age的内存地址   等于一段内存
int *page=&age;这是把age的地址存放到指针变量page中
指针*page则指向age的内存地址
一旦一个指针指向一个变量,*取值就可以获取该变量的值
所以指针*page等于age变量的值,也就是19

int *page
*page是变量age的指针 它指向变量的地址,通过指针取值可以获取到指向的变量的值,注意它不是变量,并不是说一个*page存放着19,一个age存放着19,其实就是*page=age=19,
*page和age用的是同一内存地址,访问*page就是间接访问age,*page就相当于age一个替身或分身,*其实也叫做“间接访问”运算符
而page是指针变量,他存放着变量age的地址

这里可能有点难理解,不管怎么说,学习指针是一个循序渐进的过程

其实,指针就是变量的地址,存放变量地址的变量就是指针变量
指针也是一种数据类型
在C语言中,允许一个变量存放地址,但必须这个变量的类型是指针,且不能存放非地址之类的值
因此,一个指针变量的值就是某个普通变量的地址或称为普通变量的指针
为了表示指针变量和它所指向的变量指尖的关系,所以用“*”表示指向
例如
int age;
int *page=&age;
表示 指针page指向age
*page表示取age内容的值

话说了一大堆,接下来让我们定义一个指针
首先我们定义一个表示年龄的指针
int* page; 这就是定义了一个指针,和定义普通变量就多了一个*符号而已
为什么变量名用了p开头,这里引用了英文pointer(指向),表示它是一个指针,而非普通变量,加不加p都无所谓的
*号是取值运算符,这里不是乘号的意思
*号必须放在指针类型和指针变量中间,摆在哪里无所谓
有3种方式:int* page; int *page; int * page;
第一种是比较正规的写法,第2种是用的最多的
这两种随你用哪种,但是最好不要用第3种

指针也是一种数据类型
int* 这里表示定义了指向int类型变量的指针,并不是说定义了int类型的指针
int* page
这里page是指针变量,它只能存放地址,C语言规定,只有指针类型的变量才能存放地址,不是你随随便便定义一个变量就能存放的
关于地址,每个变量都有自己的地址,且都是唯一不重复的
地址不一定全都是数字,不要以为定义int*是定义地址的类型

假设我们定义
int age=19;
int *page=&age;

age是我们定义的普通变量,且赋值了19
&age是取这个age变量的地址,这个我们用过的,scanf经常用到
&age取的地址你是可以看到的,printf("%d",&age); 这样可以用十进制的方式打印出地址
最后给你一串数字,也没啥意义
int *page=&age 是把age的地址存储到指针变量page里,换个说法就是page指针指向age的地址
定义指针的时候同时兼具两个功能
int *page=&age; 不仅我获取了age的地址,同时我也获取了age变量的值
page是指针变量,前面加个*号*page 就是取page指向age地址的值,就是取age的值
和&age一样,这是得到age的地址,那*page是得到age的值 (内容)
就是说*page=age=19
注意*page不是变量,没有哪个变量前面还带符号的吧
*page只相当于age的分身或替身
访问*page就等于访问age,修改*page同时age也跟着修改
也可以说age变量等于有两个名字
*是取值运算符,同时也叫“间接访问”运算符,听名字你也应该明白了

其实,指针就是变量的地址,是个常量(不可改变的量)
例如地址25675,它就是一个指针
能存放地址的变量就是指针变量
int* page;
page存放的地址是指针,page本身是指针变量
但常常把指针变量简称为指针,这点你要明白
一般都说page是age的指针
还有,指针变量它自己也是有地址的,也是可以被指向的,后面会学到指针的指针
指针到底好处在哪,这点以后你会慢慢感觉到

比如说整个内存就像一栋楼,变量就是这栋楼的某个房子,而指针就是这房子的门牌号
我如果要找一个变量,我不需要知道它在几楼哪个位置,我只需要得到它的指针,他的位置跟家里有几口人(内容),我就全知道了

在比如说,要去一个地方,我不需要知道这个地方在哪里,我只需要知道坐什么车能到那里,而这个车就是指针

开始指针可能有点难理解,不管怎么说,学习指针是一个循序渐进的过程

下面重新来说定义指针
int age=19;
int *page=&age;

也可以这样
int age=19;
int *page;
page=&age

这里注意不能这样
*page=&age 已经说过了*page不是变量
但是初始化可以
int *page=&age;
这样定义也许不会让你犯糊涂
int* page=&age; 反正要记得page才是指针变量 *page是取值

*是指针的一部分,可不单单是取值的作用
变量前加* 就代表这个变量是指针

定义的时候可以同时定义相同类型的但种类不一样的变量

int age,*page,a[5];
这里我同时定义了普通变量,指针变量和数组

指针要跟所指向的变量的数据类型一致
比如 char a
指针就必须定义跟它同类型的指针变量,而非int
char *pa=&a


大家要知道得到一个指针,就是同时得到它所指向变量的地址跟值
*p 不能说这个是指针,只能说p是指针 *号只是告诉你p是指针变量(有点晕)  
*p这个指针(是说p),p是得到它指向变量的地址,*p是得到它指向变量的内容



这里一个简单的指针程序,告诉你*取值的作用
#include <stdio.h>

main()
{
int a,b,*pa,*pb;
a=1,b=2;
pa=&a;
pb=&b;
printf("%d,%d\n",a,b);
printf("%d,%d\n",*pa,*pb);


}


现在看这个程序:
#include <stdio.h>

main()
{
int *p1,*p2,*p,a,b;
puts("输入两个数:");
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);

}

p1指向a p2指向b,也就是说p1存储了a的地址,p2存储了b的地址
如果a<b
p1的地址给p   p2的地址给p1 p的地址给p2
等于现在p1的地址是p2的地址,p2的地址是p1的地址
地址变了,也就是变量变了
注意,变量和地址是绑定在一起的
地址赋值给另一个指针,值也会跟着走的
现在p1重新指向了b,p2指向了a
最后在输入的时候 *p1实际是b *p2实际是a

要明白的是,a,b两个变量的值一直没有交换过,只是两个指针在交换它们两的地址
a,b的地址和值没发生任何改变

指针变量是可以改变是可以赋值的
int a ,*pa,*pb
pa=&a
可以把pa的指向给pb
pb=pa
这样pa,pb同时指向a,同是拥有a的地址

指针变量也可以不指向,就是不存放地址
int* p;
p=null;


下面我们把指针运用到函数中
我们定义一个函数,交换两个数的值
首先我们不用指针做一次:
#include <stdio.h>

main()
{
void jiaohuan(int ,int);
int a,b;
puts("输入两个数");
scanf("%d,%d",&a,&b);
jiaohuan(a,b);
printf("实参a=%d b=%d\n",a,b);

}

void jiaohuan(int a,int b)
{
     int temp;    //作为交换的中间值
    
     temp=a;
     a=b;
     b=temp;
    
     printf("交换后的a=%d,b=%d\n",a,b);
}


这里我们把实参a,b传递给函数
形参a,b是交换了值,可实参的值没有发生改变,这我们是知道的
但是我们如果用指针作为函数参数,就可以让形参改变的同时,实参同时发生改变
看下面程序
#include <stdio.h>

main()
{
void jiaohuan(int* ,int*);
int a,b,*pa,*pb;
puts("输入两个数");
scanf("%d,%d",&a,&b);
pa=&a;
pb=&b;
jiaohuan(pa,pb);
printf("实参a=%d b=%d\n",a,b);

}

void jiaohuan(int *pa,int *pb)
{
     int temp;    //作为交换的中间值
    
     temp=*pa;
     *pa=*pb;
     *pb=temp;
    
     printf("交换后的a=%d,b=%d\n",*pa,*pb);
}

我们在输入a,b的以后,用指针pa,pb分别指向a,b(就是存储它们的地址)
然后把实参pa,pb传递给函数形参pa,pb,形参pa,pb也开始指向a,b
它们的传递依然是“值传递“,它们的值就是地址
等于就是把&a,&b传递给了形参pa,pb
(int *pa,int *pb) 这里是定义的指针,并非取值

temp=*pa;
*pa=*pb;
*pb=temp;

这里不是地址交换,而是值交换,现在的*是取值了
*pa有实参a的地址,就相当于等于a了
这里*pa=a,*pb=b     其实这里就是用a,b两个替身在交换,实际上就等于a,b在交换
交换之后 *pa=b *pb=a *pa和*pb改变,a,b同时会发生改变
*pa还是之前a的地址,*pb还是之前b的地址
看这个你就会明白,a开始的地址假设是1245值是2,b是1321值是1,后面是它们的指针变量
a    2   1245---------pa(形参)
b    1   1321---------pb(形参)
发生交换之后,因为只是值交换
a   1   1245-------pa(形参)
b   2    1321-------pb(形参)

由于是根据地址修改的值,所以实参发生了改变
不用指针做函数参数,实参传递给形参的值相当是拷贝了一份给形参,所以形参怎么变都跟实参没关系
用指针做函数参数,实参传递形参是把实参的地址都传了过去,等于是自己亲自跑到被调函数里,传递给形参其实就是实参本人

数组做为形参,实参也会发生改变也是这个道理


还有temp这里不能用*temp 因为不知道它指向什么变量,它的值是不可预见的
所以这里只能用int类型,作为普通变量
其实*pa *pb 就是a,b 本来就是普通变量,temp当然也是普通变量了 

还有,如果只是地址交换的话,实参是不会发生改变的

#include <stdio.h>

main()
{
void jiaohuan(int* ,int*);
int a,b,*pa,*pb;
puts("输入两个数");
scanf("%d,%d",&a,&b);
pa=&a;
pb=&b;
jiaohuan(pa,pb);
printf("实参a=%d b=%d\n",a,b);

}

void jiaohuan(int *pa,int *pb)
{
     int* temp;    //作为交换的中间值
    
     temp=pa;
     pa=pb;
     pb=temp;
    
     printf("交换后的a=%d,b=%d\n",*pa,*pb);
}

这跟191楼的程序一样 最后pa指向b,pb指向a,只是两个指针交换地址而已
a,b地址和值没任何改变

我们知道,函数的调用只可以得到一个返回值(函数值),而运用指针变量做为参数,可以得到多个变化了的值。
下面是个排序3个数的程序:
#include <stdio.h>

main()
{
void bijiao(int* ,int*);
int a,b,c,*pa,*pb,*pc;
puts("输入三个数");
scanf("%d,%d,%d",&a,&b,&c);
pa=&a;
pb=&b;
pc=&c;
if(a>b) bijiao(pa,pb);
if(a>c) bijiao(pa,pc);
if(b>c) bijiao(pb,pc);
printf("排列后的数(从小到大)%d,%d,%d\n",a,b,c);

}

void bijiao(int *pa,int *pb)
{
     int temp;    //作为交换的中间值
    
     temp=*pa;
     *pa=*pb;
     *pb=temp;
}

如果不用指针,很难做到这一点

来源:幻想编程//所属分类:站长原创/更新时间:2014-03-08 22:40
顶一下
(14)
93.3%
踩一下
(1)
6.7%
上一篇:从零开始学编程---第一步-C语言(二十)
下一篇:从零开始学编程---第一步-C语言(二十二)
相关内容