黑马程序员_C语言基础_指针

来源:互联网 发布:ubuntu安装fcitx五笔 编辑:程序博客网 时间:2024/04/30 20:12

------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------

1、指针变量

    指针是一个常量,简单来说就是内存单元的地址;指针变量就是一个变量,记录存放地址的一个变量。

    形式:类型说明符 *变量名

A注意问题:

  1. *表示定义的是指针变量
  2. 指针变量只能存放地址,不能是数值和字符
  3. 指针变量和其他普通变量一样,也有全局变量和局部变量

B*的用法:

  1. 定义一个指针变量
  2. 获取指针变量所对应的存储单元的内容值

C初始化和引用

  1. 完全初始化:int *p=&a;即p指向了a;int *p=&a,*p1=&a;即p,p1都指向了a
  2. 部分初始化:int *p=&a,*p1;
  3. 引用:int a,*p; //定义了整型变量 a 和 指向整型变量的指针变量 p。
          p=&a;//“&”为取地址运算符,将a的地址赋给指针变量 p
          *p=a;//* p 为指针变量 p 所指向的存储单元的内容,即 p 所指向的变量的值

D调用函数

    指针变量可以作为函数参数,它可以将一个变量的地址传送到另一个函数中,在调用过程中会临时分配存储空间,调用完之后内存空间也会随之释放。     

    调用过程中实参变量和形参变量之间的数据传递是单向的“值传递”方式,指针变量作函数参数在传递也是单向的值传递,不可能通过调用函数来改变实参指针变量的值,但可以改变实参指针变量所指向变量的值。要想实现通过调用函数改变实参的值,可以通过调用实参的地址,通过改变形参指向实参的地址来达到改变实参的值。

下面三种情况都是调用函数,传递的形参分别为值,地址的情况,对实参的影响。

1)、

void swap2(int a,int b){//定义中间变量int temp;//进行值的交换temp = a;a = b;b = temp;}int main(int argc, const char *argv[]){//定义两个变量并赋值int a = 3, b = 4;printf("交换之前的值:a=%d,b=%d\n", a, b);//调用函数swap2(a, b);printf("交换之后的值:a=%d,b=%d\n", a, b);return 0;}

结果:


分析:在主函数进行swap2(a, b);时,开始调用子函数,这时候为子函数分配了一个存储空间,并有变量a,b,进行交换,虽然此时执行完语句进行a,b的调换,但是子函数掉用完释放空间,形参并没有传递给实参,实参还是原来的值。

2)、

void swap2(int *a,int *b){//定义中间变量int *temp;//进行值的交换temp = a;a = b;b = temp;}int main(int argc, const char *argv[]){//定义两个变量并赋值int a = 3, b = 4;printf("交换之前的值:a=%d,b=%d\n", a, b);//调用函数swap2(&a, &b);printf("交换之后的值:a=%d,b=%d\n", a, b);return 0;}

结果:

分析:在主函数进行swap2(&a, &b);时,开始调用子函数,这时候为子函数分配了一个存储空间,传递的是a,b的地址,这个时候定义了临时中介的地址,此时执行语句进行交换的是a,b的地址,并没有改变a,b的值,但是子函数掉用完释放空间,实参还是原来的值。

3)、满意结果值交换

void swap2(int *a,int *b){//定义中间变量int temp;//进行值的交换temp = *a;*a = *b;*b = temp;}int main(int argc, const char *argv[]){//定义两个变量并赋值int a = 3, b = 4;printf("交换之前的值:a=%d,b=%d\n", a, b);//调用函数swap2(&a, &b);printf("交换之后的值:a=%d,b=%d\n", a, b);return 0;}

结果:

分析:在主函数进行swap2(&a, &b);时,开始调用子函数,这时候为子函数分配了一个存储空间,传递的是a,b的地址,根据形参*a指向实参a地址,这个时候定义了临时中介的值,通过执行下面的语句*a,*b进行改变交换的是实参a,b的值,子函数掉用完释放空间,实参值已经被交换。

2、二级指针

简单而言就是指向指针的指针。

用图的形式表示如下:

例子:

int a=5;//定义一个整型变量为5

int  *p=&a;//定义一个指针变量指向变量a地址,则可以描述为p=&a,*p=a=5

int  **p1=&p;//定义一个二级指针变量指向变量p地址,则可以描述为p1=&p,*p1=p=&a,**p1=*p=a=5

3、数组指针

A定义:数组元素的指针就是数组元素的地址。

一般形式为:int a[10];int *p;p=a=&a[0]=首元素的地址。

B初始化

若指针变量 p 已指向数组元素中的一个元素的地址,则p+1指向同一数组中的下一个元素地址。

指向下一个元素的值表达用*p++或*(p+1),但是不能用数组名*(a+1)表示,因为数组名是一个常量,不能这样使用。

C引用一个数组元素的方法

1)下标法。如 a[i] 形式;

2)指针法。如*(p+i)或 *(a+i)。其中 a 是数组名,p 是指向数组元素的指针变量,起初值 p=a。

实例:用指针实现逆序数组的输出

void nixu(int a[],int len){//定义数组指针指向aint *p = a;//定义下标int i = 0, j = len - 1;int temp;while (i<j){temp = *(p+i);*(p + i) = *(p + j);*(p + j) = temp;//修改下标i++, j--;}}int main(int argc, const char *argv[]){int a[6] = { 3, 5, 8, 4, 9, 7 };//调用逆序函数nixu(a, 6);//遍历数组for (int i = 0; i < 6; i++){printf("%d   ", a[i]);}printf("\n");return 0;}

4、一维指针数组

定义:一个数组的元素的值为指针就是指针数组。

形式:类型说明符  *数组名[数组长度]        即:int *a[3]={&a,&b,&c};

如:int *a[3];//表示的是一个指针数组,有3个元素,每个元素是一个指针,且都指向整型变量

int a=3,b=4,c=5;int *p[3]={&a,&b,&c};

打印输出指针数组第一个元素的值可以用&a,p[0]表示;

打印输出指针数组第一个元素的地址可以用&p[0],p表示;

5、数组名访问二维数组

定义一个二维数组int a[i][j];

则a代表的是第0行的首地址,a+i代表的是行号为i行的首地址;

行指针可以表示为:a+1,a[1],*(a+1)=&a[1][0];

列指针可以表示为:a[0]==&a[0][0],a[0]+1==&a[0][1].

总结:a[i]+j代表的是a[i][j]的地址,*(a[i]+j)获取的是a[i][j]的值,

此外(*(*a+i)+j)代表a[i][j]的值,且*(*a+i)+j==*(a[i]+j)

6、二维数组指针

形式:数据类型  (*指针变量名)[二维数组列数],行指针越来指向二维数组的每一行,存放的是行的首地址。

例:int a[2][3]; int (*p)[3]=a=&a[0]=&a[0][0]=a[0];

这儿要注意它和一维指针数组的区别使用。

7、字符串指针

它存放的是每个字符串的首地址。

形式:char *变量名=“字符串内容”;字符串内容是常量。

字符指针变量和字符数组的关系
    1)字符数组由若干个元素组成,每个元素中放一个字符,而字符指针变量中存放的是地址(字符串第一个字符的地址)
    2)赋值方式。对字符数组只能对各个元素赋值,
         char str[]="Hello world!";//字符数组赋值方式,它可以在定义时整体赋初值,但不能在赋值语句中整体赋初值。如:str[]="Hello world!"这样赋初值是不行的。
         char *a;  a="Hello world!";//字符指针变量的赋值方式,a是字符串第一个元素的地址。
     3)对字符指针变量赋初值。
         char *a="Hello world!";等价于 char *a;  a="Hello world!";//字符指针变量可以在赋值语句中整体赋初值。
     4)若定义了一个字符数组,在编译时为它分配了内存单元,他有确定的地址,但是字符指针变量若未对它赋初值,则它将指向一个不确定的字符数据。
     5)指针变量的值可以改变,但是字符数组名不能改变。
          char *a="Hello world!"; a=a+7;
     6)用指针变量指向一个格式字符串,可以用它代替printf函数中的格式字符串。
           char *format="a=%d,b=%f\n";
           printf(format,a,b);

例:对字符串排序,按照升序方式。

void sortstring(char *a3[],int len){//冒泡排序char *temp;//临时存放地址for (int i = 0; i < len-1; i++){for (int j = 0; j < len - 1 - i; j++){//比较字符串大小用函数if (strcmp(a3[j], a3[j + 1])>0){//实现交换temp = a3[j];a3[j]=a3[j+1];a3[j + 1] = temp;}}}}int main(int argc, const char *argv[]){//输入5个字符串并按字母顺序排列char *a3[5] = { "wer", "ad", "fgg", "rt", "bg" };for (int i = 0; i < 5; i++){printf("%s\n", a3[i]);}printf("\n");sortstring(a3, 5);for (int i = 0; i < 5; i++){printf("%s\n", a3[i]);}return 0;}

总结:指针和数组结合起来使用是非常有用的,也是一个重点难点,要好好体会。


------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------



0 0
原创粉丝点击