基本知识:在内存中的每个字节都有一个编号,这就是“地址”,相当于旅馆中的房间号。记住,内存单元的地址和内存单元的内容是两个不同的概念。

程序在编译之后,就已经将变量名转换成变量地址,对变量值的存取都是通过地址进行的。按照变量地址存取变量值的方式称为“直接存取方式”,或直接访问方式。另一种是“间接存取方式”:将变量i的地址存放在另一个变量中。可以在变量中定义这样的一些变量,专门是用来存放地址的。例如,i_pointer用来存放一个整形变量的地址,编译系统给这个变量分配4个字节(假设是3010到3013字节),通过下面语句将i的起始地址(3000)存放到i_pointer中。----->    i_pointer=&i;

其中&是取地址运算符,&i是变量i的地址。执行此语句后,i_pointer的值就是3000(即变量i所占用的起始地址)。若要取出i的值,可以直接访问,也可以采用间接方式:先找到存放“i的地址”的变量i_pointer。然后从中取出i的地址(3000),然后到3000开始的4个字节中取出i的值(3)。由于通过地址能找到所需的变量单元,所以说,地址指向该变量单元。因此将其形象化的称为“指针”。意思是通过它能访问以它为地址的内存单元。一个变量的地址称为该变量的指针。例如整形变量i的地址是3000,因此3000就是整形变量i的指针。------------------------------------》》指针就是地址,地址也就是指针。

1.变量和指针

变量的指针就是变量的地址。用来存放变量地址的变量是指针变量。指针变量是指向另外一个变量。c++中用“*”符号来表示“指向”,例如i_pointer是一个指针变量,而*i_pointer表示i_pointer所指向的变量。

2.定义指针变量

记住:所有变量在使用前必须定义,也就是指定其类型,这样是为了在编译时可以按照类型分配存储空间。

int *i_pointer,*j_pointer。这里开头的int是指:所定义的指针变量是指向整形数据的指针变量,也就是说这两个变量只能存放整形数据的变量的地址,而不能存放浮点型或其他类型的数据的地址。

注意:

(1)i_pointer,j_pointer是变量名,而*i_pointer,*j_pointer不是变量名,“*”不是指针变量的一部分,在定义变量时在变量名前加上一个“*”表示该变量是指针变量。

(2)不能用一个整数给一个指针变量赋初值,int *i_pointer=2000是错误的。可以将已经定义的变量的地址作为指针变量的初值。int i;int *i_pointer=&i;

(3)在定义指针变量时,必须指定基本类型。因为在“使指针移动1个位置”时或者“使指针值加1”时,在不同的类型中,使地址值增加的字节数是不同的。例如,整形数据,使“指针加1”意味着地址值加4字节,而对于双精度数据,则意味着地址值增加8个字节。

3.引用指针变量

有两个与指针变量有关的运算符:

(1)& 取地址运算符;(2)指针运算符(或称间接访问运算符)

如:&a为变量a的地址,*p为指针变量p所指向的单元。

关于“*”和“&”的一些说明:

一。“&*pointer_1=&a”的含义是什么?“*”和“&”的优先级相同,所以是自左至右的方式结合。因此是先进行*pointer_1的运算,它就是变量a。在执行&运算,即可得到a的地址。

二。”*&a“的含义是什么?先进行&a运算,得到a的地址,在进行*运算,得到a所指向的变量。

4.指针作为函数参数

函数的参数不仅可以是整型,浮点型,字符型等数据,还可以是指针类型。作用是将一个变量的地址传送给被调用的形参。

注意:在调用函数的时候,函数的形参应该有int,如void swap(int *pa,int *pb){   };而调用实参时候,只写变量,不用写类型,如swap(pointer_1,pointer_2)。

void swap(int x,int y)

{int temp;

temp=x;

x=y;

y=temp;

}

通过实参void swap(a,b)调用void swap(int x,int y)来进行值传递。a的值传给了x,b的值传给了y。在执行完调用后,x和y的值换了,但是实参a和b的值并没有换,也就是说由于虚实结合是采用单向的“值传递”方式,只能从实参向形参传递,形参值的改变无法回传给实参。

但是,可以使用指针变量所指向的变量值发生变化,函数调用后,这些变量值的变化依然保留下来了,这样就实现了“通过调用函数使变量的值发生变化,在主调函数中使用这些改变了的值”的目的。

感悟:如果想通过函数调用得到n个要改变的值,可以采用下面的步骤:

1.在主调函数中设n个变量,用n个指针变量指向他们;

2.编写被调函数,其形参为n个指针变量,这些形参指针变量应当与主调函数中的n个指针变量具有相同的基类型;

3.在主调函数中将n个指针变量作实参,将他们的值(是地址)传给所调用函数的n个形参指针变量,这样,形参指针变量也指向这n个变量;

4.通过形参指针变量的指向,改变该n个变量的值;

5.在主调函数中就可以使用这些改变了值的变量。

切记:实参变量和形参变量之间的数据传递是单向的“值传递”方式。指针变量作为函数参数也要遵守这一规则。

当看到类似于这样的一些函数:viod exchange(int *,int *,int *)和void swap(int *,int *)的时候;直接应该很快地判定这是声明基本类型为整型的指针变量。

C++ 指针 部分的更多相关文章

  1. TODO:Golang指针使用注意事项

    TODO:Golang指针使用注意事项 先来看简单的例子1: 输出: 1 1 例子2: 输出: 1 3 例子1是使用值传递,Add方法不会做任何改变:例子2是使用指针传递,会改变地址,从而改变地址. ...

  2. enote笔记法使用范例(2)——指针(1)智能指针

    要知道什么是智能指针,首先了解什么称为 “资源分配即初始化” what RAII:RAII—Resource Acquisition Is Initialization,即“资源分配即初始化” 在&l ...

  3. C++虚函数和函数指针一起使用

    C++虚函数和函数指针一起使用,写起来有点麻烦. 下面贴出一份示例代码,可作参考.(需要支持C++11编译) #include <stdio.h> #include <list> ...

  4. C++11 shared_ptr 智能指针 的使用,避免内存泄露

    多线程程序经常会遇到在某个线程A创建了一个对象,这个对象需要在线程B使用, 在没有shared_ptr时,因为线程A,B结束时间不确定,即在A或B线程先释放这个对象都有可能造成另一个线程崩溃, 所以为 ...

  5. c 数组与指针的使用注意事项

    数组变量和指针变量有一点小小的区别 所以把数组指针赋值给指针变量的时候千万要小心 加入把数组赋值给指针变量,指针变量只会包含数组的地址信息 而对数组的长度一无所知 相当于指针丢失了一部分信息,我们把这 ...

  6. Marshal.Copy将指针拷贝给数组

    lpStatuss是一个UNITSTATUS*的指针类型实例,并包含SensorDust字段 //定义一个数组类型 byte[] SensorDust = new byte[30] //将指针类型拷贝 ...

  7. C++智能指针

    引用计数技术及智能指针的简单实现 基础对象类 class Point { public: Point(int xVal = 0, int yVal = 0) : x(xVal), y(yVal) { ...

  8. EC笔记:第三部分:17、使用独立的语句将newed对象放入智能指针

    一般的智能指针都是通过一个普通指针来初始化,所以很容易写出以下的代码: #include <iostream> using namespace std; int func1(){ //返回 ...

  9. 智能指针shared_ptr的用法

    为了解决C++内存泄漏的问题,C++11引入了智能指针(Smart Pointer). 智能指针的原理是,接受一个申请好的内存地址,构造一个保存在栈上的智能指针对象,当程序退出栈的作用域范围后,由于栈 ...

  10. 智能指针unique_ptr的用法

    unique_ptr是独占型的智能指针,它不允许其他的智能指针共享其内部的指针,不允许通过赋值将一个unique_ptr赋值给另一个unique_ptr,如下面错误用法: std::unique_pt ...

随机推荐

  1. 比较synchronized和读写锁

    一.科普定义 这篇博文的两个主角“synchronized”和“读写锁” 1)synchronized 这个同步关键字相信大家都用得比较多,在上一篇“多个线程之间共享数据的方式”中也详细列举他的应用, ...

  2. java基础学习日志--异常案例

    package test7; public class InvalidScroreException extends Exception { public InvalidScroreException ...

  3. 木块问题(The Blocks Problem,Uva 101)

    不定长数组:vector vector就是一个不定长数组.不仅如此,它把一些常用操作“封装”在了vector类型内部. 例如,若a是一个vector,可以用a.size( )读取它的大小,a.resi ...

  4. [POJ1155]TELE(树形背包dp)

    看到这道题的第一眼我把题目看成了TLE 哦那不是重点 这道题是树形背包dp的经典例题 题目描述(大概的): 给你一棵树,每条边有一个cost,每个叶节点有一个earn 要求在earn的和大于等于cos ...

  5. TestNG异常测试

    用@Test(expectedExceptions = xxx) 声明 package com.janson; import org.testng.annotations.Test; public c ...

  6. eclipse c/c++配置

    先下载jdk,如果jdk装的是32位,eclipse也要下载32位的,64位也是一样.我用的是jdk7 64位. 下载eclipse,去官网上下载最新的http://www.eclipse.org/d ...

  7. day21 01 包的初识

    day21 01包的初识 包:把解决一类问题的模块放在同一个文件夹里面-----包(一个包里面通常会含有_init_.py文件(python2里面必须有),但是后面的就没有要求一定要有了) 同样导入的 ...

  8. 【Codeforces 484A】Bits

    [链接] 我是链接,点我呀:) [题意] 让你求出l~r当中二进制表示1的个数最多的数x [题解] 最多有64位 我们可以从l开始一直增大到r 怎么增大? 找到l的二进制表示当中0所在的位置 假设i这 ...

  9. vue.js通讯----父亲拿儿子的数据

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

  10. $inject的用法

    controller后面的$inject是用来注入函数的变量名称的