C++学习笔记(四)--指针
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++学习笔记(四)--指针的更多相关文章
- Go语言学习笔记四: 运算符
		Go语言学习笔记四: 运算符 这章知识好无聊呀,本来想跨过去,但没准有初学者要学,还是写写吧. 运算符种类 与你预期的一样,Go的特点就是啥都有,爱用哪个用哪个,所以市面上的运算符基本都有. 算术运算 ... 
- C#可扩展编程之MEF学习笔记(四):见证奇迹的时刻
		前面三篇讲了MEF的基础和基本到导入导出方法,下面就是见证MEF真正魅力所在的时刻.如果没有看过前面的文章,请到我的博客首页查看. 前面我们都是在一个项目中写了一个类来测试的,但实际开发中,我们往往要 ... 
- IOS学习笔记(四)之UITextField和UITextView控件学习
		IOS学习笔记(四)之UITextField和UITextView控件学习(博客地址:http://blog.csdn.net/developer_jiangqq) Author:hmjiangqq ... 
- java之jvm学习笔记四(安全管理器)
		java之jvm学习笔记四(安全管理器) 前面已经简述了java的安全模型的两个组成部分(类装载器,class文件校验器),接下来学习的是java安全模型的另外一个重要组成部分安全管理器. 安全管理器 ... 
- Learning ROS for Robotics Programming Second Edition学习笔记(四) indigo devices
		中文译著已经出版,详情请参考:http://blog.csdn.net/ZhangRelay/article/category/6506865 Learning ROS for Robotics Pr ... 
- Typescript 学习笔记四:回忆ES5 中的类
		中文网:https://www.tslang.cn/ 官网:http://www.typescriptlang.org/ 目录: Typescript 学习笔记一:介绍.安装.编译 Typescrip ... 
- ES6学习笔记<四> default、rest、Multi-line Strings
		default 参数默认值 在实际开发 有时需要给一些参数默认值. 在ES6之前一般都这么处理参数默认值 function add(val_1,val_2){ val_1 = val_1 || 10; ... 
- muduo网络库学习笔记(四) 通过eventfd实现的事件通知机制
		目录 muduo网络库学习笔记(四) 通过eventfd实现的事件通知机制 eventfd的使用 eventfd系统函数 使用示例 EventLoop对eventfd的封装 工作时序 runInLoo ... 
- python3.4学习笔记(四) 3.x和2.x的区别,持续更新
		python3.4学习笔记(四) 3.x和2.x的区别 在2.x中:print html,3.x中必须改成:print(html) import urllib2ImportError: No modu ... 
- 零拷贝详解 Java NIO学习笔记四(零拷贝详解)
		转 https://blog.csdn.net/u013096088/article/details/79122671 Java NIO学习笔记四(零拷贝详解) 2018年01月21日 20:20:5 ... 
随机推荐
- 深入理解js闭包【写的通俗易懂,很值的阅读】
			详细内容在下面这个链接里面: https://www.cnblogs.com/uedt/archive/2010/10/28/1863389.html 能写出这样的文章,定是大佬! 
- 10-js对象、数组
			# js对象 ```1.使用原始的方式创建内置对象 var myObject = new Object(); myObject.name = “lijie”; myObject.age = 20; m ... 
- em、rpx和px的换算
			rpx:对于小程序开发,所用的单位都是rpx,而不论哪个型号的手机,屏幕宽度都是750rpxrpx与px的转换,根据设计稿换算例如:设计稿750px宽度,ps上量出或者标出的宽度是多少,那么就定义多少 ... 
- Solr的学习使用之(九)facet.pivot实战
			facet.pivot自己的理解,就是按照多个维度进行分组查询,以下是自己的实战代码,按照newsType,property两个维度统计: public List<ReportNewsTypeD ... 
- OC学习--面向对象的个人理解
			1. 什么是面向对象? 以下一段话是我在百度上找的解释: 面向对象(Object Oriented,OO)是软件开发方法.面向对象的概念和应用已超越了程序设计和软件开发,扩展到如数据库系统.交互式界面 ... 
- SCRUM REPORT DIRECTORY
			Alpha sprint scrum 1 scrum 2 scrum 3 scrum 4 scrum 5 scrum 6 scrum 7 scrum 8 scrum 9 scrum 10 Beta s ... 
- HTTP RESTful服务开发 spring boot+Maven +Swagger
			这周配合第三方平台整合系统,需要提供HTTP REST服务和使用ActiveMQ推送消息,研究了下,做个笔记. 1.使用eclipse创建Spring Boot项目 创建Spring Boot项目( ... 
- 手写split功能
			def split_new(stringstr, charstr): """ :param stringstr: 要分割的串 :param charst ... 
- JFreeChart使用
			最近项目需要做图形分析,就想到了使用JFreeChart,之前也没有使用过,就现学先用吧.本文主要记录一些主要的代码及学习使用过程. 使用JFreeChart步骤: 一.下载JFreeChart.ja ... 
- mysql order by 自定义
			TIMESTAMPDIFF 语法: TIMESTAMPDIFF(interval,datetime_expr1,datetime_expr2). 说明: 返回日期或日期时间表达式datetime_ex ... 
