请先看C++中的指针概述,这里只是扩充

数组指针

  其实这里主要说的就是c++中的指针运算

  1. /*
  2.  
  3. 数组元素指针:
  4. 一个变量有地址,一个数组包含若干个元素,每个数组元素都有相应的地址,
  5. 指针变量可以指向数组元素(把某一元素的地址放到一个指针变量中)
  6. 所谓数组元素的指针就是数组元素的地址
  7. 可以用一个指针变量指向一个数组元素
  8.  
  9. int a[10]={1,2,3,4,5,6,7,3,2,3};
  10.  
  11. int *p;
  12.  
  13. p=&a[0]; 等同与 p=a; 等同与 int *p=a; 等同与 int*p=&a[0]
  14.  
  15. 注意:
  16. 1) 数组名a不代表整个数组,只代表数组首元素的地址
  17. p=a 的作用是"把a数组的首元素的地址赋给指针变量p",而不是"把数组a各个元素的值赋给p"
  18.  
  19. 数组指针:
  20. 指向数组元素的指针
  21.  
  22. 数组指针的作用:
  23. 使用数组指针间接访问数组的元素
  24.  
  25. 数组指针的定义:
  26. int *p;
  27.  
  28. 数组指针的初始化;
  29.  
  30. int a[4] ={1,2,3,4};
  31. int *p = a;//数组指针,定义了一个指针变量p赋值数组的首地址(第一个元素的地址),P指向数组的第一个元素
  32.  
  33. int *p = &a[0];//等价上面一句话
  34.  
  35. 数组指针如何访问数组的元素:
  36. 1) p+1 表示指向数组的下一个元素
  37. 2) p-1 指向数组的上一个元素
  38.  
  39. 误区:
  40. 用数组指针遍历数组
  41. for(int i=0;i<4; i++){
  42. printf("%d\t",*p++);
  43. }
  44.  
  45. //学习的误区: 数组名 a 是一个常量 等同与 *(10++)
  46. //数组名++ 这是错误的
  47. printf("*a=%d\n",*a++);//这种写法是错误的
  48.  
  49. */

逆序数组:把数组中的内容前后对调

  1. void nixuArrayint a[],int len){
  2. int i=0,j=len-1;
  3. while(i<j){
  4. temp=*(p+i);
  5. *(p+i)=*(p+j);
  6. *(p+j)=temp;
  7. //修改下标
  8. i++,j--;
  9. }
  10. }

一维指针数组

  1. 指针数组的定义:
  2.  
  3. 数据类型*数组名[数组长度];
  4.  
  5. int* pa[3];
  6.  
  7. //定义一个指针数组,数组名是pa,可以用来存放3个指针(必须是int类型变量的指针);
  8.  
  9. 指针数组的使用:
  10.  
  11. int a=3,b=4,c=5;
  12.  
  13. int *pa[3] ={&a,&b,&c};
  14.  
  15. pa[0] a的地址
  16.  
  17. pa 数组的首地址,又是变量a的地址
  18.  
  19. //使用数组名来访问 a的值
  20.  
  21. printf("%d\n",**pa);
  22.  
  23. int a1[2][2]={1,2,3,4};
  24.  
  25. //定义了一个指针数组,赋值为a1[0]是第一行的指针
  26. int *pa1[2]={a1[0],a1[1]};
  27. printf("**pa1=%d\n",**pa1);
  28.  
  29. //*pa1 取到的是指针数组pa1中首地址的值= a1[0]
  30. //同时a1[0] = a1的首地址
  31. *pa1 = a1[0]
  32.  
  33. printf("&a1[0] = %d\n",a1[0]);
  34.  
  35. printf("*pa1 = %d\n",*pa1);
  36.  
  37. //正推
  38. //所以 **pa1 即 *(*pa1)=*(*pa1[0])=*(a1)=*(a1[0])=*(&(a1[0][0]))=a1[0][0] =1;
  39. //**(pa1+1)=*(*(pa1+1))=*(*pa1[1])=*(a1[1])=*(&(a1[1][0]))=a1[1][0]=3
  40.  
  41. //逆推
  42. //所以想拿数字2的时候 就相当于
  43. 2=a1[0][1]=*(&a1[0][1])=*(&a1[0][0]+1)=*(a1[0]+1)=*(a1+1)=*(*pa1[0]+1)=*(*pa1+1)
  44. //拿数字3
  45. 3=a1[1][1]=*(&a1[1][1])=*(&a1[1][0]+1)=*(a1[1]+1)=*(pa1[1]+1)=*(*(pa1+1)+1)

数组名访问二维数组

  1. 公式 *(*(a+i)+j) == a[i][j]

用普通指针访问二维数组

//这种写法虽然也可以获取到二维数组中的元素,但是这样写是不符合规范的,利用了内存存储的机制

数据在内存中存放的方式,从高地址依次向下存放

  1. int a[3][4]={1,2,3,4,5,6,7,8,9,10,11,12};
  2.  
  3. int *p=a
  4.  
  5. for(int i=0;i<12;i++){
  6. printf(" %d \n",*(p+i));
  7. }

二维数组指针

  1. 一般形式:
  2. 数据类型 (*指针变量名)[二维数组列数];
  3. 其中"类型说明符"为所指数组的数据类型. “*” 标示其后的变量是指针类型
  4.  
  5. 如要将二维数组赋给一指针,应这样赋值:
  6. int a[3][4];
  7. int (*p)[4]; //该语句是定义一个数组指针,指向含4个元素的一维数组
  8. p=a; //将该二维数组的首地址赋给p,也就是a[0]或 &a[0][0]
  9. p++; //该语句执行过后,也就是p=p+1; p 跨过行a[0][] 指向行a[1][]
  10.  
  11. 所以数组指针也称指向一维数组的指针
  12.  
  13. 遍历二维数组的元素
  14.  
  15. int a[3][4]={1,3,4,5,6,7,8,9,10,13,15,17};
  16.  
  17. int (*p)[4]=a;
  18.  
  19. 所以之前遍历中的 数组a 可以替换为 p :*(*(p+i)+j)

指针数组和二维数组指针变量的区别

  1.    int *pa[3]={&a,&b,&c}; pa是一个指针数组
  2. int *pa1[2]={a[0],a[1]}
  3. int (*pa)[3] ;//二维数组指针
  4.  
  5. 应该注入指针数组和二维数组指针变量的区别,这两者虽然都可以用来标示二维数组,但其表示方法和意义是不同的
  6. 二维数组指针变量是单个的变量,其一般形式中(*指针变量名)两边的括号不可少,而指针数组类型表示的是多个指
  7. 针(一组有序指针)在一般形式中"*指针数组名"两边不能有括号.
  8. 例如:
  9. int(*p)[3]; //表示一个指向二维数组的指针变量,该二维数组的列数为3或分解为一维数组的长度为3
  10. int *p[3]; //表示p是一个指针数组,有三个下标变量p[0],p[1],p[2]均为指针变量

字符串指针

  1. char *变量名 ="字符串内容" // "字符串内容"是常量
  2. //当指向的为'' 单引号时,为字符指针 ""双引号时为字符串指针

字符串指针与字符数组的区别

  1. //字符串指针 指向可以改变
  2. char *ss="abc";
  3.  
  4. ss="bcd";
  5.  
  6. //字符数组
  7. char s1[]="abc";
  8. s1="hello" 这是错误的 可以改变里面的内容但是不能重新指向

指针函数

  1. 一个函数的返回值类型是指针,我们就称为指针函数
    格式:
        类型说明符 * 函数名( 形参表){
            函数体
        }
  2.  
  3. 例:
        //返回两个数中的大数的地址
        //返回的是形参x 和 y 中大数的地址
        int * max( int x,int y){
          printf("x= %p\n",&x);
          printf("y= %p\n",&y);
          return x>y?&x:&y;
        }

函数指针

  1. 函数指针
  2. C语言中,一个函数总是占用一段连续的内存区,而函数名就是该函数所占内存区的首地址。
  3.  
  4. 我们可以把函数的这个首地址(或称入口地址)赋予一个指针变量,使该指针变量指向该函数.然后通过指针变量就可以找到并调用这个函数.我们把这种指向函数的指针变量称为"函数指针变量"
  5.  
  6. 函数指针定义方法:
  7. 函数指针变量定义的一般形式为:
  8. 类型说明符 (*指针变量名)(函数的参数);
  9. 其中"类型说明符" 表示被指函数的返回值的类型
  10. "(* 指针变量名 )" 表示 "*" 后面的变量是定义的指针变量
  11.  
  12. 函数的声明:
  13.  
  14. int sum(int a,int b);----->函数指针 int (*p)(int a,int b);
  15.  
  16. //定义了一个函数指针p
  17. //p可以存放返回值是int类型, 并且有两个形参,形参的类型还都是int类型的函数的地址
  18.  
  19. //函数指针的初始化
  20. p = sum;//sum存得就是函数在内存中的首地址
  21.  
  22. //定义函数指针的时候,可以不用写形参名
  23. int (*p)(int int);
  24.  
  25. 函数指针的使用
  26.  
  27. 1.定义函数指针
  28. int(*p) (int int);
  29. 2.给函数指针初始化
  30. p=sum;
  31. 3.用函数指针间接的调用函数
  32. int s=p(23,45);
  33.  
  34. 函数指针的用处:
  35.  
  36. 例如 + - x /时 ,只需要判断符号 ,然后 p = sum / p = jian 就可以

  

C语言中的指针的更多相关文章

  1. C语言中的指针数组

    C语言中的指针数组是什么,像 char *a[]={"ddd","dsidd","lll"}; 这里讲一下注意如果我们使用了a也就是首元素的 ...

  2. 【ZZ】C 语言中的指针和内存泄漏 & 编写高效的C程序与C代码优化

    C 语言中的指针和内存泄漏 http://www.ibm.com/developerworks/cn/aix/library/au-toughgame/ 本文讨论了几种在使用动态内存分配时可以避免的陷 ...

  3. GO语言中的指针

    http://www.tizgrape.com/?p=100 Go语言中的指针语法和C++一脉相承,都是用*作为符号,虽然语法上接近,但是实际差异不小. Go使用var定义变量: var v6 *in ...

  4. C语言中的指针笔记

    C语言指针 得到变量的地址 可以使用&运算符找到变量保存在内存中的位置 int x = 1; printf("x的内存地址是"%p\n",&x) %p格式 ...

  5. C语言中的指针加减偏移量

    C语言指针偏移技巧(也是一个要注意的坑) - 陈杰柱的博客 - CSDN博客  https://blog.csdn.net/cjzjolly/article/details/82116772 C语言中 ...

  6. C 语言中的指针和内存泄漏

    引言对于任何使用 C 语言的人,如果问他们 C 语言的最大烦恼是什么,其中许多人可能会回答说是指针和内存泄漏.这些的确是消耗了开发人员大多数调试时间的事项.指针和内存泄漏对某些开发人员来说似乎令人畏惧 ...

  7. C语言中的指针和内存泄漏

    引言 对于任何使用C语言的人,如果问他们C语言的最大烦恼是什么,其中许多人可能会回答说是指针和内存泄漏.这些的确是消耗了开发人员大多数调试时间的事项.指针和内存泄漏对某些开发人员来说似乎令人畏惧,但是 ...

  8. C语言中的指针学习(小黑板)

    指针是C语言中的精华所在,也是C语言的危险之在,今天又重现温习了一下C语言,做了一下总结. 欢迎批阅. (1)指针的含义指针的本质也是数据类型,它是指向地址的变量.例如: { int a = 10; ...

  9. [C]C语言中的指针和内存泄漏几种情况

    引言 原文地址:http://www.cnblogs.com/archimedes/p/c-point-memory-leak.html,转载请注明源地址. 对于任何使用C语言的人,如果问他们C语言的 ...

  10. 论C语言中二级指针和二维数组之间的区别

    刚开始学习C语言的时候,觉得一个数组可以定义一个一级指针去访问,想当然的就觉得可以定义一个二级指针去访问二维数组.很显然这是错误的. 我们来看看C语言的数组在内存中的存储方式. 实际上C语言中的数组, ...

随机推荐

  1. ECSHOP info: Can't Connect MySQL Server(localhost:3306)!

    今天对服务器压力测试后,某个公司电脑的页面显示标题所示,别人电脑正常.故让她清理cookie.无效.重启MySQL后问题解决.

  2. vue组件递归

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  3. 多边形剪裁img

    <!DOCTYPE html><html><head> <meta charset="utf-8"/> <title>& ...

  4. MYSQL性能优化--分库分表

    1.分库分表 1>纵向分表 将本来可以在同一个表的内容,人为划分为多个表.(所谓的本来,是指按照关系型数据库的第三范式要求,是应该在同一个表的.) 分表理由:根据数据的活跃度进行分离,(因为不同 ...

  5. ECMAScript版本号总结

      最近想要研究下ES6,关于这个标准的发展历史.ES5. ES6.ES2015等等名称的定义都不怎么明确,查了很多资料,去除了程序员不关心的信息,下面是对ECMAScript规范发展历史及名词定义的 ...

  6. 关于js参数传递矛盾新理解

    之前看了很多人的解释,说js中,函数的参数传递都是值传递中不理解. 他们无非举了两个例子 在这两个例子中,第二个例子可以看出参数是由值传递的.因为函数内对象的变化没有影响到函数外对象的变化.但是在第一 ...

  7. Oracle函数整理

    ) from dual;--绝对值 ,) from dual;--取模,取余数 select ceil (12.1) from dual;--去上限值 select floor (12.1) from ...

  8. Struts2的类型转换(上)

    传统的类型转换.(略) Struts2中提供了内置的基本的类型转换器,可以实现基本类型的自动转换,包括: Integer, Float, Double, Decimal Date and Dateti ...

  9. 【Egret】WebSocket 的使用说明

    在Egret里可以使用WebSocket ,也可以使用socket.io 首先先深入了解一下 WebSocket 在Egret里的机制,看这篇文章: 主要讲解Egret里使用WebSocket和pro ...

  10. 老李分享:《Linux Shell脚本攻略》 要点(四)

    老李分享:<Linux Shell脚本攻略> 要点(四)   1.IP地址的正则表达式: [0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3} 2. ...