您的位置:首页 > 编程语言 > C语言/C++

c语言中认识指针

2015-10-29 20:58 260 查看
地址和变量的概念

指针

作用:

1、表示复杂的数据结果(eg:链表、树、)

2、能动态分配内存

3、方便的使用字符串

4、有效而方便使用字符串

5、有效而方便的使用数组

&&&调用函数的时候能够获得1 个以上的结果。

6、能够直接处理单元地址等

总结:可以看到可以很直接的接触到计算机的硬件的内容进行操作。

1、数据的存储和读取:

定义一个变量,程序在编译的时候,会给这个变量分配内存单元。

(依据:系统会根据程序中定义的变量的类型,分配一定的长度空间。eg:32位机,int分配2位字节,char分配1位字节,浮点型分配4个字节,内存中每一个字节都有一个编号,这个就是“地址”,地址标志内存单元,而内存单元是用来存放数据的。)

内存单元的内存和内存单元的地址的区别:

程序:

int i,j,k;

编译的时候,分配内存:

2000,2001分配给i,

2002,2003分给给j,

2004,2005分配给k;

即为:内存单元的内容就是地址中存放的数据,而地址就是2000~2005等。

在程序中,一般是“通过变量名”来对内存单元进行存取操作的。(程序员对变量以及方法的使用)

实际上,计算机中的实际运行为:计算机编译程序之后,将变量名转化为变量的地址,对变量的存取都是通过地址来进行的。

总结:从程序员的角度可以看到一种别名的方式,从计算机的角度上看是实际的操作。

eg:

printf("%d",i);

(编译的时候会将i这个变量,编译成为一个对应的地址)

找到i变量的地址(2000),从2000开始的两个字节取出数据,然后输出。

scanf("%d",&i);

将键盘中输入的值存放到i对应的地址上(i整形变量的地址为:2000,2001)。

若是:

k = i+ j;

将i(2000,2001)存放的值和j(2002,2003)存放的值进行相加,送到k所占用的内存地址为2004,2005的内存地址上。

这种变量地址存取变量值的方式成为“直接访问”方式。

总结:我们可以回顾一个“微机”课程上的汇编的集中方式。

另一种访问的方式:

简介访问:即为将变量的地址存放在另外一个变量中。

(c语言中的类型变量的定义)c语言中,程序可以定义整形变量、字符变量、实型变量。

同时也是可以定义这样的一个变量的,就是用它来存放地址。

eg:我们定义一个变量t_pointer 用来存放整形的变量地址。它被分配为3010,3011这两个字节,可以通过下面的语句将i的地址(2000)存放在这个变量中。

t_pointer = &i;所以这个时候的t_pointer的值就是2000(即为它的值就是i的变量的地址的起始地址2000);

下面来了解一下简介方式进行对数值进行存储:

先找到i的地址存放的遍历t_pointer,然后从里面获取i的地址(2000),然后懂啊2000,2001里面获取相应的i的值。

这个就是中间多了一个变量。============>(间接存储(地址变量))

总结一下:i的变量

1)、直接方式,就是知道i它的地址,然后直接获取i的值;直接通过i的变量的i的地址量进行对i的值得访问。

2)、将i的变量的地址,存放到另外一个专门是用来存放地址的变量中。所以在访问的时候需要通过存放地址的-变量获取到相应的的地址 ,然后通过地址来获取i值。

(所谓的“指向”,就是存放内存的地址来进行相应的指定,这样就可以通过这个变量来访问它所指向的地址的位置。)

通常:

我们经常会说,通过地址指向能够找到所需要的单元,可以说地址指向待单元变量。

因此:地址形象化为指针。意思即为:通过它能够找到以它为地址的内存单元。(eg:根据地址2000就能够找到变量i的存储单元,从而读取其中的值。)

一个变量的地址称为这个变量的指针。上述:2000是i的指针,t_pointer就是一个指针变量。 指针变量的值就是地址(或者说是:指针)

区分指针变量和指针:

eg:变量i的指针是2000,而不能够说i的指针变量是2000,i的指针变量是t_pointer。明白啥为变量。

3)、指针就是一个地址,而指针变量就是一个存放地址的变量。、

再一次总结:
(1)指针(地址)同意概念,指针变量就是存放地址的变量。

(2)直接存储不存在指针变量的问题,而间接存储需要涉及到变量。

变量的指针和指向变量的指针变量

变量的指针就是变量的地址,存放变量的地址的变量就是指向变量的指针变量。

为了表述指针变量和 它所指向的变量的关系,可以使用“*”来表示。

eg:(*t_pointer )是t_pointer所指向的变量。

i = 3;

*t_pointer = 3; 即为:将3赋值给指针变量t_pointer所指向的变量。

1、定义一个指针变量

(c语言(强类型语言)固定每一个变量在使用之前必须先定义,指定类型,并且按此来分配内存单元)

指针变量定义为指针类型。

eg:

一般的:int i,j;  //定义两个整形变量i,j

指针的: int *t_pointer_1,*t_pointer_2;//定义两个指针变量,

指针类型中:左端的int是在定义指针变量的时候,必须指定的“基本类型”,指针变量的“基本类型”用来规定了指针变量可以指向的变量的类型。上面的两个指针可以指向基本类型为int的,而不能够指向浮点类型的数据。

第一的格式:

基本类型 * 指针变量名;

eg:

float * pointer_3;

char * pointer_4;

指针变量之间的的赋值。

如何使指针指向另外一个变量呢?

eg:

t_pointer_1 = &i;

t_pointer_2 = &j;

所以:将变量i的地址存放在指针变量t_pointer_1中,因此,pointer_1就指向了变量 i;j也是同样。

这个时候*t_pointer_1 就表示是i的值。

定义指针变量的时候注意两点:

(1)指针变量的前面的“ * ”表示该变量的类型为指针型变量。指针变量名是t_pointer_1,而不是(*t_pointer_1),这个和其他的基本类型的定义不同。

(2)定义指针变量的时候,必须指定基本的类型。

原因:不同的基本的类型,指针所指向的位置的移动等等操作是不一样的。

eg:如果指针指向的是“整形变量”,那么使“指针移动一个位置”意味着移动2个字节;使指针+1 意味着地址的值加2个字节。如果指针-指向的是浮点型,那么指针增加的不是2而是4。

同时,指针变量只能够指向一种类型的变量,不能够指向其他类型的变量。

下面的错误的例子:

float a;

int *pointer ;

pointer = &a;(错误的)

总结:

1)、指针变量的定义以及符号“*”的含义。

2)、定义指针变量的时候定义好基本的类型,并且一种类型的指针只能够指向它当前类型的指针,可以联想指针的增减操作。

2、指针变量的引用

两个有关的运算符:

(1)& :取地址运算符

(2)* :指针运算符(或者“简介访问”运算符),取其指向的内容。

eg:&a 为变量a的地址,*p为指针变量p所指向的存储单元的内容(即:p所指向的值)。

eg:如下代码

#include <stdio.h>
void main()
{
int a,b;
int *pointer_1,*pointer_2;
a = 100;b=10;
pointer_1 = &a;//把变量a地址赋值给pointer_1
pointer_2 = &b;//把变量b的地址赋值给pointer_2
printf("%d,%d \n",a,b);
printf("%d,%d \  n",*pointer_1,*pointer_2);
}


结果:

100,10

100,10

说明:

(1)&*pointer的含义是什么?(pointer是指针变量)“&”和“*”两个云算符的优先等级是相同的,但是按照自右边而左边方向结合。因而先进行*pointer,在执行&,相当于&(*pointer)一般是这样写,结果即为:a的地址。

(2)*&a的含义是什么?先进行&a(a为基本的类型),即为a的地址,然后在进行*运算,就是a地址指向的变量a。结果即为:a的值。

即为上面的两个是等价的。

(3)(*pointer)++ 相当于a++,括号是必要的。没有括号为:*pointer++ (++ 和* 是等级是相同的),结合运算是自右向左的。所以相当于*(pointer++)。由于++在pointer的值是改变的,这样pointer不再指向a了。

代码:
#include <stdio.h>
void main()
{
int *p1,*p2,*p,a,b;
scanf("%d,%d",&a,&b);
p1 = &a; p2 = &b;
if(a<b){
p = p1;
p1 = p2;
p2 = p;
}
printf("a=%d,b=%d \n\n",a,b);
printf("max=%d,min=%d \n",*p1,*p2);
}
结果:

5,9  //输入

a=5,b=9   //输出

max=9,min=5

说明:a和b并没有交换,他们依旧保持原值。但是p1和p2的值改变了。p1的开始是&a,后来是&b。p2原来的值是&b,后来的值是&a。

(这个方法不是交换两个整形变量的值,而是交换两个指针变量的值)

总结:
1)、指针变量的使用,注意它的的操作符号。

2)、指针的变量操作的时候,改变的是指针变量中存放的地址。而不会直接去改变它所指向的变量的值,像上面。

除非使用*符号来获取值进行改变。

3、指针变量作为函数的参数

函数的参数不经可以是整型、浮点型、字符型等数据,还可以是指针类型。

所用是:将一个变量的地址传送到另一个函数中。

代码:
#include <stdio.h>
void swap(int *p1,int *p2);
int main()
{
int a,b;
int *pointer_1,*pointer_2;
scanf("%d,%d",&a,&b);
pointer_1 = &a;
pointer_2 = &b;
if(a<b) swap(pointer_1,pointer_2);
printf("%d,%d \n",a,b);
return 0;
}
(1)
void swap(int *p1,int *p2)
{
int temp;
temp = *p1;
*p1 = *p2;//这种方式改变该地址指向的变量的值
*p2 = temp;
}
结果:

5,6  //输入

6,5  //输出

说明;

实参pointer_1 、pointer_2是指针变量,在函数调用的时候,将实参的变量的值传给形参变量,采取的依然是“值传递”方式,这里的“值传递”中的值是地址值。

虚实结合了之后,p1的值是&a,p2的值是&b。这个时候p1和pointer_1是指向同一个变量a,p2和pointer_2同样指向一个变量b。

swap函数体内,使*p1 和*p2 的值互换。也就是a,b的值交换。函数结束了之后p1,p2 销毁,所以交换了数值。

(注意:这里交换的是a,b的值,而不是p1,p2的值。) 这个改变不是通过形参传回给实参实现的,而是通过形参的地址变量和实参指向同一个变量来实现的。

(2)有问题的代码:
void swap(int *p1,int *p2){
int *temp;
*temp = *p1;
*p1 = *p2;
*p2 = *temp;
}
运行结果:

5,9

Segmentation fault (core dumped) 分割故障(核心转储)

原因:*temp是指针变量temp所指向的变量。但temp中并无确定的值(它的值是不可预见的),因此temp所直线的单元也是不可以预见的。(也即是temp里面存放的值是不确定,随时改变,如果*temp存放了值之后,再来取不一定是原来的值)

因此,对*temp赋值有可能给一个存储重要数据的存储单元赋值。这样会破坏系统的正常工作状况。所以,应该讲*p1的值赋值给一个临时变量实现。

(3)
void swap(int x,int y ){
int temp;
temp = x;
x =y;
y = temp;
}
这里的结果是不会改变的,因为函数是单向传递值的,这里并没有地址等概念,只是存储的数值的单向传递。即为函数调用结束了之后,就会销毁。

解说一下(1)的原理:用指针变量所谓函数参数,在函数执行的过程中使指针变量所指向的变量值发生变化,函数调用结束后,这些变量值得变化依然保留下来,这样就实现了“通过调用函数使变量的值发生变化,而主函数可以使用这些改变了的值”。

(4)注意不要企图改变指针形参的值而是指针的实参的值改变。
void swap(int *p1, int *p2){
int *p;
p = p1;
p1 = p2;
p2 = p;
}
编程者的思想:交换pointer_1 和 pointer_2 的值,是pointer_1指向值大的变量。

设想:

(1》》先是pointer_1指向a,pointer_2指向b,

(2》》调用swap函数,将pointer_1 的值传给p1,pointer_2的值传给p2;

(3》》在swap函数里面,使p1与p2的值交换。

(4》》形参p1,p2将地址传回实参pointer_1,pointer_2,想得到输出:9,5 。

但是,不行的。程序输出的结果还是:5,9;

问题出现在第4步:

c语言中实参变量和形参变量之间的数据传递是单向的“值传递”方式,指针变量作为参数也是要遵循这个原则。

不可能通过调用函数来改变实参指针变量的值,但可以改变实参指针变量所指变量的值,像(1)。

使用函数只能够得到一个返回值,而运用指针变量做参数,可以得到多个变化的值(如:(1)所示)[因为它相当于在另外一个入口进行对同一个变量的值操作]。

总结:

(1)指针变量作为参数,同样是“值传递”,单向传递。不过这里传的是指针的值。

(2)函数只可以返回一个值,而指针作为参数,可以对多个值的改变。是通过指针变量所指向的变量的值的而改变。

总结

(1)知道指针、地址、指针变量等等概念。

(2)指针的定义以及符号的使用

(3)指针作为函数的参数进行传递,可以改变多个值。解决了一个函数只能够返回一个值的作用。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: