指针的用法


指针是c语言的一个特色。

1 将地址形象的比喻为指针。

2 访问的两种形式:1 直接访问:比如定义了变量a,然后通过变量名a直接访问

      2 间接访问:定义a,得知a的地址,由于地址指向变量,所以可以直接 访问。

3 除了整型,实型,字符型,还有一种是存放地址的变量。Int * a;a= &p;

4 一个变量的地址我们称之为指针;一个存放别的变量地址的变量叫做指针变量;指针变量的值就是指针(即地址);如果存放的指针指向的数据是整形,则我们说这个指针变量是指向整形变量的指针变量。

 

<重中之重>指针变量:1 程序中两处 * :声明与使用。

声明: * 指示后面的变量是指针变量,且其基类型是前面的类型。

使用: * 运算符,把地址转向所指向的变量。

 

  2可以在定义时同时对他进行初始化。

  3 必须指定基类型:因为他指代的数据类型有可能是int long 等等,而在后续要进行指针的加减,指针加一,如果是int 则增加24个字节,如果是long,则8个字节。所以一定要指定。

  4 赋给指针的变量一定是地址,而不能是其他数据类型。

  5 给指针变量赋值:1直接赋值 p=&a;

2 引用赋值 如果*p=1;之前必须p=&a;否则会因为不知道地址而有可能会占用有用的地址。

          6 注意指针变量也是一个变量,所以在指针变量的范畴内,各种变量的赋值都可以,就和变量一样,而和普通变量交互,则需要有地址,有基变量。

 

<第一个重点>

重重重重:1 单向的值传递:即实参传递过去的形参,之后是形参来回变换,与实参无关。2 由于地址本身就存在,不存在什么变化,所以,只能够通过地址指向的值来回改变。

          指针可以作为函数参数

要点:1(单向的值传递) 所有都要与之结合。

要点:2(址变换) 3(*址变换) 4(值变换)只有4不可以改变原值

重点:不可能通过调用函数来改变实参指针变量的值,但是可以实参指针变量所指向的值。

函数的参数不仅可以是整形,实数型,字符型,数组型,也可以是指针型。

他的目的是址传递。

 

<A>我们的问题是如何使原值改变。函数参数传值,传完之后回来,看是否原值改变。

以两个数要变换为例。

首先采用(值传递),由于是单向传递,况且要想改变原数据,必须要从指针(地址)这方面下手,所以,即不可以改变原值;

然后是(址传递),由于传过来之后,实参要赋给形参,而此时在变换函数(swap)形参来回变换,也就是实参不变换,而形参变换,所以没用,且是单向的。所以不能改变原值。

然后是(*地址)传递,自己画图,实参传过来之后,由于虽然还是改变形参,但是改变的是形参上对应的数字,即改变原地址上对应的数字,即可以改变原值。

 

 

 <误区> 就是说以前虽然是值传递,但是值传递回来return之后赋给了新的变量,既然是新的变量,所以输出了之后肯定是改变数据的,这就是产生错觉的原因。

总结难点:1 单向的值传递:即实参传递过去的形参,之后是形参来回变换,与实参无关。2 由于地址本身就存在,不存在什么变化,所以,只能够通过地址指向的值来回改变。

 

<第二个重点>:通过指针引用数组。

1 数组元素的指针就是数组元素的地址。

2 引用数组可以用下表法,也可以用指针法。

重:3 数组名(不包括形参的数组名)可以与首元素地址等价。即 int * p;p=ap=&a[0];

重:4 指针法   *a+i*(p+i);这两者都是指向a[i]

5 指针运算:

1  首先指针运算的p++不是简单地加一,而是根据变量类型的字节数去加一。如果是int 则可能是+2 +4,如果是float,则是+4

2  可以使用p++,因为他是变量,而不能使用a++,因为a是常量。

重:注意p+ia+i的区别,a+i是自身的地址直接加字节数,而p+i是把地址赋给另一个指针变量去进行加减。

6  写程序时要注意此时指针的位置,因为就算超出,他实际上也不会报错。

7  也可以使用p[i],但是注意此时一定要知道当前p在什么位置,如果一开始P指向a[2],p[3]则是a[5],所以不建议使用这种方式.

8 <重中之重>:用数组名做函数参数:

1  形参数组的值发生变化,实参也发生变化(注意:形参的值指的是指针的值而不是地址【上一节指针做参数的三种情况】)

重:2  void f(int arr[],int n)=====等价于void f(int * arr,int n);

3  指针变量在visual c++里占据4个字节。

4  实参数组名是一个常量,而形参数组名是一个变量,所以可以赋值,而常量不可以赋值即a=a+3(a是常量),不能使用,而(arr=arr+3)是可以的;

 

 

<第三个重点>:通过指针引用字符串

1 表示字符串的两种方法:1 用字符数组2 用指针指向字符串的字符。

2 指针法:char * string=”I love china”; printf(“%s”,string);

3 不能够重新赋值,因为字符常量是不能改变的。

重:4 实际上是把字符串的第一个字符的地址赋给指针变量,然后输出会自加(这就是不用遍历的原因),最后遇到\0会停止(这才是可以自加的真正原因吧,因为可以自动停止)。

重:5 为什么输出地址就可以输出字符?数组就需要*?

应该是编译器的处理,因为字符数组即char a[]遍历就需要*a.

6 输出的时候还是用字符数组。

<重中之重>

1 传递参数可以用数组名,即地址,也可以用指针。

重:2 字符数组除了比数字数组多了一种方法,首先他俩同时都可以传递数组名和数组首地址,当然首地址是用另一个变量,并且由于他还可以这么定义char * string=”i love china”;所以还可以直接把string传递,其实本质是一样的,都是地址,只不过编译器对他进行了优化(遍历,不用加*),所以其实都是一样的。

 

实参形参的数组名与指针?

3 最后要自己加上\0;

4 最后就是写法问题???

重:5作为实参,可以用数组名(不带中括号),可以用char * p(其中p=a&a[0]),即变量;还可以用char * string=”aaaaaa”,直接把string传入。当然,前两种就是和数字数组是一样的。即字符数组和数字数组基本上是一样的,只不过多了一种写法。

作为形参,本可以用数组名和指针变量,但是不知道为啥数组名行不通,暂且就是指针变量把。

6 字符数组可以再赋值,字符指针变量不可以。

 

 

重重重重:都是地址(基本上是一个,数组则是首地址)的传入传出,所以可以对原值改变。

重重重重:当想改变原值的时候,比如int a;在改变值的函数内部,一定要赋值,

举个例子:#include<stdio.h>

 

int main(){

void change(int * m);

int a=10;

int *p;

p=&a;

change(p);

printf("%d",a);

return 0;

}

void change(int * m){

* m=* m+1;//注:这里一定要给*m赋值,之前的错误是只有*m+1,而没有赋值,结果当然不会改变。

}

 

重重重重:字符型实参传递参数的形式:1 数组名 2 数组首地址 3 string 注:前两种形式都是字符数组,最后一种是指针型字符数组。

字符型形参应该是 1 * 2 m[]:两种都行,但是现在给第一种赋值遇到一些问题。

附代码:#include<stdio.h>

int main()

{

void change(char * m);

char * string="Ia love China";

char a[19]="I love china";

//change(&a[0]);

change(string);

//传递参数的形式:1 数组名 2 数组首地址 3 string 注:前两种形式都是字符数组,最后一种是指针型字符数组

//change(string);

printf("%s\n",a);

return 0;

}

void change(char  * m){

//形参应该是 1 * 2 m[]:两种都行,但是现在给第一种赋值遇到一些问题。

*m='u';//这里现在遇到一些问题

}

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM