1.指针(变量的地址):
  指针变量:存放指针(地址)的变量
  直接存取(访问):按变量地址取值
  间接存取(访问):将变量的地址放入指针变量中
  定义指针变量:基类型 *指针变量名

2.与指针有关的运算符:
  &:取地址运算符
  *:指针运算符(间接访问运算符);
  int *pointer_1,*pointer_2;
  int a = 1, b = 2;
  pointer_1 = &a;
  pointer_2 = &b;
  pointer_2 = &*pointer_1;//*,&优先级一样,自右至左结合,所以是先取a的值,再取a的地址&a给指针变量pointer_2
  若有*&a,表示的是先取a的地址,再取a的值。

3.谨记:函数传参:实参->形参 之间的数据是单向传递的“值传递方式”,指针变量也遵守这一原则,调用函数时,不会改变实参指

针变量的值,但可以改变实参指针变量所指向的值。所以可以利用指针来改变主调函数中多个变量的值,不用指针变量来实现这个是

很难实现这一点的。

4.数组元素的指针就是数组元素的地址

  int a[10];
  int *pointer;
  pointer = a[0];与pointer = a; 等价都表示数组的第一个元素的地址。

  如果初始:pointer = a; 以下都为此前提,那么:
  pointer+1 = a+1 = a[1] //实际地址看类型,pointer+1*n 或者 a+1*n 或者&a[1]
  所以有pointer+i = a+i = a[i] pointer+i*n a+i*n &a[i] 例:int型n=4;

  所以可以看出[]是变址运算符,对a[i]的处理是这样的:先按a+i*n计算数组元素的地址,然后由此地址找出所指向的单元的


  指向数组元素的指针变量也可以带下标,如:pointer[i]与*(pointer+i)等价。
  所以引用数组元素有两种方法:
  a.下标法:a[i];
  b.指针法:*(a+i)或者*(pointer+i);使用这种方法能使目标程序质量高(占运行内存小,运行速度快)
  ·注意:指针变量可以指向有效的数组元素,也可以指向数组以后的内存单元。例:
  int a[10], *p = a;
  cout <<*(p+10);//编译不会提示出错。

  5.如果先使p=a,即p指向数组a的首元素:
  (1).p++(或p+=1):使p指向下一元素,即a[1],如果用*p,则得到a[1]的值;
  (2).*p++: ++与*优先级相同,右结合,相当于*(p++),所以是先取*p的值,再使p++。
  例如:
  for(p=a;p<a+10;p++)
  cout <<*p ; //可改写为:
  for(p=a;p<a+10; )
  cout <<*p++;
  (3).*(p++):先取*p值,p再加1
  *(++p):先p加1,再取*p值,二者区别仅在于p++ 与 ++p 的含义。
  (4).(*p)++:先取*p的值,再使取得的值加1.
  (5).如果p当前指向a[i]:
  *(p--): 先取*p的值,即a[i],再使指针变量p指向a[i-1];
  *(++p): 先使指针变量自增1,指向a[i+1],再取*p的值a[i+1];
  *(--p): 先使指针变量自减1,指向a[i-1],再取*p的值a[i-1];

6.使用指针变量作函数参数接收数组地址
因为数组作形参时接收的也是实参数组的首地址,所以可以用指针变量来接收以数组为实参的参数,例如:
  void select(int array[]);//实际上可以表示为
  void select(int *array );/*编译器实际上是将数组名作为指针变量来处理的。所以实际上,在函数调用时并不存在一个

  占有存储空间的形参数组,只有指针变量。*/

7.多维数组与指针:
  int arr[3][4];假设arr起始为2000

  (1)C++中规定了数组名作为首地址,所以
  arr[0]是arr[0][0]的首地址,arr[1]是arr[1][0]的首地址即&arr[1][0],
  arr[0]+1,表示arr[0][1]的地址,arr[0]+2表示的是arr[0][2]的地址;
  *(arr[0]+2) 表示a[0][2]的值。所以有
  arr[i]+j 表示&arr[i][j],
  *(arr[i]+j) 表示arr[i][j]的值。
  (2)arr,表示首行地址&arr[0],则a+1表示第二行起始地址&arr[1],其值为2000+4*4=2016;
  arr[1]+1: 表示 &arr[1][1],所以有
  arr[i]+j: 表示 &arr[i][j],
  *(arr[i]+j):表示 arr[i][j]的值,因为arr[i] = *(arr+i);所以
  *(*(arr+i)+j): 也表示arr[i][j]的值。
  (3)指向数组元素的指针变量:
#include<iostream>
using namespace std;

int main(){

  int array[3][4] = {1,2,3,4,5,6,7,8,9,10,11,12};
  int *p;
  p = array[0];//注意此处是array[0],而不是array,要符合指针类型。
  cout <<"--------------" <<endl;
  for( p; p<array[0]+12;p++ )
  cout <<*p<< ' ';
  cout <<endl;
  cout <<"--------------" <<endl;
  return 0;
}
(4)指针变量指向由m个元素构成的一维数组
#include<iostream>
using namespace std;

int main(){

  int a[3][4] = {1,2,3,4,5,6,7,8,9,10,11,12};
  int (*p)[4],i,j;/*(*p)[4]是一个指针变量,它指向包含4个整型元素的一维数组,()不可丢,
否则变成*p[4],[]优先级高,变成了指针数组
*/
  p = a;//p指向a[0];
  cout <<"please input i,j:";
  while(1){
    cin >>i >>j;
    if( i>=3||j>=4 )
    cout <<"warning:i must less then 3,j must less then 4,please try a again:" <<endl;
    else break;
  }
  cout <<"---------------------" <<endl;
  cout <<*(*(p+i)+j);
  cout <<endl <<"---------------------" <<endl;
  return 0;
}

8.指向数组的指针作函数参数(一维数组名,多维数组名也可,之前有讲过)
#include<iostream>
using namespace std;

int main(){

  void output(int (*p)[4]);
  int a[3][4] = {1,2,3,4,5,6,7,8,9,10,11,12};
  output(a);//a指向a[0]
  return 0;
}

void output(int (*p)[4]){//注意形参声明为指向一维数组的指针变量,而不是int型指针变量

  int i,j;
  for( i=0;i<3;i++ )
    for( j=0;j<4;j++ )
      cout <<*(*(p+i)+j) <<" ";
  cout <<endl;
}

9.字符指针(C++中共3种方法访问一个字符串,之前已经学习过两种)
(1)用字符指针指向一个字符串
#include<iostream>
using namespace std;

int main(){

  char *str = "I love China!";//对字符指针变量str的初始化其实是把字符串第一个元素的 地址 赋给str
  //等价于 char *str; str = "I love China"; 输出时,系统先输出str指向的第一个字符数据,
  //然后str+1,使之指向下一个字符,然后输出......直至遇到'\0'为止,在内存中,字符串的末尾
  //被自动加了一个'\0'
  cout <<str<<endl;
  return 0;
}
(2)利用字符指针实现对字符串的存取
#include<iostream>
using namespace std;

int main(){

  char str1[] = "I love liu_xiao_min",str2[20];
  char *p1,*p2;
  p1 = str1;
  p2 = str2;
  for( ;*p1!='\0';p1++,p2++ )
  *p2 = *p1;//其实string str1 = "I love liu_xiao_min",str2;str2 = str1;最简单快捷
  *p2 = '\0';
  p1 = str1;
  p2 = str2;
  cout <<p1 <<endl;
  cout <<p2 <<endl;
  return 0;
}

10.函数与指针
(1)用函数指针变量调用函数(原理:一个函数被编译时被分配一个入口地址。这个函数入口地址就称为函数的指针)
函数指针定义:
函数类型 (*指针变量名)(函数形参表);
例:
#include<iostream>
using namespace std;

int main(){

  int max( int x, int y );
  int (*p)( int, int );//(*p)括号不能漏
  int a,b,n;
  p = max; //函数名代表函数入口地址
  cin >>a >>b;
  m = p( a,b );
  cout <<"max=" <<m<<endl;
  return 0;
}
int max( int x, int y ){

  int z;
  if( x>y )
    z = x;
  else
    z = y;
  return z;
}

(2)用指向函数的指针作函数参数
类似:float intern(float a, float b, float (*fun)(float));

11.指针函数(函数返回值为指针的函数)
指针函数定义:
函数类型 *函数名(参数表列);
例:
#include<iostream>
using namespace std;

int main(){
  int *a(int a);
  int i = 10;
  cout <<a( 10 ) <<endl;
  return 0;
}

int *a( int a ){

  return &a;
}

12.指针数组(一个数组,其元素全部为指针类型数据)

一维指针数组:
类型名 *数组名[数组长度];

例:int *a[3]; //注意与int (*a)[3];的区别,后者是指向含有3个整型元素的一维数组的指针变量

#include<iostream>
#include<cstring>
using namespace std;

int main(){

void sort( char *name[], int n );//指针数组做函数参数
void print( char *name[], int n );

  char *name[] = { "BASIC","FORTRAN","C++","Pascal","COBOL" };//指针数组
  int n = 5;
  sort( name,n );
  print( name,n );
  return 0;
}

void sort( char *name[], int n ){ //选择法排序

  char *temp;
  int i,j,k;
  for( i=0;i<n-1;i++ ){
    k = i;
     for( j=i+1;j<n;j++ ){
    if( strcmp( name[k],name[j] )>0 )//name[x]中存放各个字符串的首地址
      k = j;
    }
    if( k!=i ){
    temp = name[i];name[i] = name[k];name[k] = temp;
    }
  }
}

void print( char *name[] , int n ){

  int i;
  for( i=0;i<n;i++ )
  cout <<name[i] <<endl;
  }
输出:
BASIC
C++
COBOL
FORTRAN
Pascal

13.指向指针的指针(指向 指针数据 的指针)
如12所述,数组name[x]是一个指针数组,此时设一个指针变量p,它指向指针数组元素的元素,则p就是指向指针型数据的指

针变量。
定义一个指向指针数据的指针:
char *(*p);//可以写成 char **p;
分析:
char *p:表示指向字符型数据的指针变量(即字符指针变量)。
char *(*p):表示p指向的是字符指针数据
例:
#include<iostream>
using namespace std;

int main(){

  char **p;//定义指向 字符指针数据 的指针变量p
  char *name[] = { "BASIC","FORTRAN","C++","Pascal","COBOL" };
  p = name + 2; //指向name[2]
  cout <<*p <<endl;//输出name[2]中指针指向的字符串的值
  cout <<**p <<endl;//输出name[2]指向的字符串中的第一个字符
  return 0;
}
输出:
C++
C
分析:
由于*p代表name[2],它指向字符串"C++",即在name[2]中存放了字符串"C++"的第一个字符串的地址,因此"cout <<*p <<endl;"就

是从第一个字符开始输出字符串"C++"。第二个cout中的**p是*p(值为name[2])指向的"C++"第一个字符元素的内容,即字符"C",所以

第二个cout语句输出"C".

C++学习笔记(四)--指针的更多相关文章

  1. Go语言学习笔记四: 运算符

    Go语言学习笔记四: 运算符 这章知识好无聊呀,本来想跨过去,但没准有初学者要学,还是写写吧. 运算符种类 与你预期的一样,Go的特点就是啥都有,爱用哪个用哪个,所以市面上的运算符基本都有. 算术运算 ...

  2. C#可扩展编程之MEF学习笔记(四):见证奇迹的时刻

    前面三篇讲了MEF的基础和基本到导入导出方法,下面就是见证MEF真正魅力所在的时刻.如果没有看过前面的文章,请到我的博客首页查看. 前面我们都是在一个项目中写了一个类来测试的,但实际开发中,我们往往要 ...

  3. IOS学习笔记(四)之UITextField和UITextView控件学习

    IOS学习笔记(四)之UITextField和UITextView控件学习(博客地址:http://blog.csdn.net/developer_jiangqq) Author:hmjiangqq ...

  4. java之jvm学习笔记四(安全管理器)

    java之jvm学习笔记四(安全管理器) 前面已经简述了java的安全模型的两个组成部分(类装载器,class文件校验器),接下来学习的是java安全模型的另外一个重要组成部分安全管理器. 安全管理器 ...

  5. Learning ROS for Robotics Programming Second Edition学习笔记(四) indigo devices

    中文译著已经出版,详情请参考:http://blog.csdn.net/ZhangRelay/article/category/6506865 Learning ROS for Robotics Pr ...

  6. Typescript 学习笔记四:回忆ES5 中的类

    中文网:https://www.tslang.cn/ 官网:http://www.typescriptlang.org/ 目录: Typescript 学习笔记一:介绍.安装.编译 Typescrip ...

  7. ES6学习笔记<四> default、rest、Multi-line Strings

    default 参数默认值 在实际开发 有时需要给一些参数默认值. 在ES6之前一般都这么处理参数默认值 function add(val_1,val_2){ val_1 = val_1 || 10; ...

  8. muduo网络库学习笔记(四) 通过eventfd实现的事件通知机制

    目录 muduo网络库学习笔记(四) 通过eventfd实现的事件通知机制 eventfd的使用 eventfd系统函数 使用示例 EventLoop对eventfd的封装 工作时序 runInLoo ...

  9. python3.4学习笔记(四) 3.x和2.x的区别,持续更新

    python3.4学习笔记(四) 3.x和2.x的区别 在2.x中:print html,3.x中必须改成:print(html) import urllib2ImportError: No modu ...

  10. 零拷贝详解 Java NIO学习笔记四(零拷贝详解)

    转 https://blog.csdn.net/u013096088/article/details/79122671 Java NIO学习笔记四(零拷贝详解) 2018年01月21日 20:20:5 ...

随机推荐

  1. Elasticsearch7.X 入门学习第一课笔记----基本概念

    原文:Elasticsearch7.X 入门学习第一课笔记----基本概念 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https: ...

  2. java 进销存管理 商户管理 库存管理 springmvc SSM 项目源码

    统介绍: 1.系统采用主流的 SSM 框架 jsp JSTL bootstrap html5 (PC浏览器使用) 2.springmvc +spring4.3.7+ mybaits3.3  SSM 普 ...

  3. em、rpx和px的换算

    rpx:对于小程序开发,所用的单位都是rpx,而不论哪个型号的手机,屏幕宽度都是750rpxrpx与px的转换,根据设计稿换算例如:设计稿750px宽度,ps上量出或者标出的宽度是多少,那么就定义多少 ...

  4. localeCompare按首字母排序汉字

    sort() 方法用于对数组的元素进行排序. 如果想按照其他标准进行排序,就需要提供比较函数,该函数要比较两个值,然后返回一个用于说明这两个值的相对顺序的数字.比较函数应该具有两个参数 a 和 b,其 ...

  5. ShellExecute指定IE浏览器打开

    ShellExecute(NULL,L"open", L"iexplore.exe", L"www.baidu.com", NULL, SW ...

  6. 随笔3 HashMap<K,V>

    equals.hashcode和==的区别 在介绍HashMap之前,我想先阐述一下我对这三者的理解,equals这个方法呢,就是在判断是否为同一对象(注意,这里的同一对象和相同的内存地址是不同的), ...

  7. alert(1) to win 9

    function escape(s) { function htmlEscape(s) { return s.replace(/./g, function(x) { return { '<': ...

  8. 开发zeroc ice应用入门(java开发ice应用,python开发ice应用,java与python结合开发ice服务)

    ice作为一种rpc框架,为主流平台设计,包括Windows和Linux,支持广泛的语言,包括C++,Java,C#(和其他.Net的语言,例如Visual Basic),Python,Ruby,PH ...

  9. nginx proxy大文件上传失败问题总结

    问题描述: http://www.syhuo.net ota.apk包上传正常 http://www.syhuo.net:8080 ota.apk包上传不正常 查看nginx error日志 [roo ...

  10. Windows无法启动MapGIS DataStorage Service服务

    但是启动又启动不了,查看属性 发现计算机服务器确实少了该文件目录.. 可能是不小心删除了? 之前确实有删过一些文件 下次直接把.net禁止就可以了,不用删除,不然不小心删除了其它服务.. 参考文献:h ...