原创 四、关于指针

2011-8-6 14:39 1356 10 10 分类: MCU/ 嵌入式

指针与内存之间的关系就像是电脑中桌面图标与可执行程序所在路径的关系,简单的说它是内存里面的快捷方式。指针与整形,字符型等一样,也是一种数据类型,指针所存储的并不是数据本身而是数据在内存中的地址。指针变量的声明方式是:

指针类型  *指针变量名称

用“&”可以获取变量或常量在内存中的地址,指针声明时最好初始化,不然指针乱指容易出问题,空指针用“NULL”因为C++对大小写敏感,所以一定是大写的“NULL”;将一个常量的地址赋给指针变量可能导致通过指针改变常量,所以不合法。下面写个小程序测试一下:

/*

* Copyright (c) 2011,菜鸟在行动之--C++学习日志

* All rights reserved.

* 

* 文件名称:main.cpp

* 文件标识:LESSON8-1-MAIN1

*     要:学习使用指针

* 

* 当前版本:1.0

*     者:懒猫爱飞

* 完成日期:20110715

*

* 取代版本:无 

* 原作者  :无

* 完成日期:无

*/

#include <iostream.h>

/*

 * 函数名称:int main(void)

 * 函数功能:主函数

 * 入口参数:无

 * 出口参数:无

 *     注:无

*/

int main()

{

int i = 9;

int *iptr = &i;   // i的地址赋指针iptr

int **pp = &iptr; // iptr的地址赋给指针pp

cout << "i在内存中的地址是:  " << iptr << endl;  // 输出变量i在内存中的地址

cout << "i的值是: " << *iptr << endl;            // 输出变量i的值

cout << "iptr在内存中的地址: " << pp << endl;   // 输出指针iptr在内存中的地址

cout << "指针pp所指向的内容: " << *pp << endl; // 输出指针pp所指向的内容

cout << "测试一下指针的指针: " << **pp << endl;

*iptr = 2+*iptr;

cout << "iptr所指向的内容是:" << *iptr << endl; // 输出指针iptr所指向的

return 0;

}

通过程序测试知道,指针也是一个变量,在内存中也有地址,间接引用指针以后就和使用指针指向的变量一样方便。

对于指针类型来说可以使用的运算有:和整数做加法运算,和整数做减法运算,两指针做关系运算,指针的乘除法运算是没有意义的也是不通允许的。指针和整数C的加减法是指针向前或向后移动C个对应类型的存储区,可以用下面的公式表示:

新地址 == 旧地址 ± C*每个对应数据类型在内存中所占的字节数

继续写个小程序验证:

/*

* Copyright (c) 2011,菜鸟在行动之--C++学习日志

* All rights reserved.

* 

* 文件名称:main.cpp

* 文件标识:LESSON8-2-MAIN1

*     要:学习使用指针2

* 

* 当前版本:1.0

*     者:懒猫爱飞

* 完成日期:20110715

*

* 取代版本:无 

* 原作者  :无

* 完成日期:无

*/

 

#include <iostream.h>

 

/*

 * 函数名称:int main(void)

 * 函数功能:主函数

 * 入口参数:无

 * 出口参数:无

 *     注:无

*/

int main()

{

int a[5] = {1,2,3,4,5};

int *aptr = a; // 将数组a的首地址赋给指针aptr

int i = 1;

 

for(int j=0; j<5; j++)

{

     cout << "内存(" << aptr <<")中的值是:" << *aptr <<endl;

     aptr += 1;    // 地址加1;

}

 

return 0;

}

运行结果如下图所示:

<?xml:namespace prefix = v /><?xml:namespace prefix = o />

 

 

 

 

8-1 运行结果

数组并不是一个普通的变量,而是指向数组首过元素的指针,也就是说我们可以用数组名来初始化一个对应类型的指针,虽然数组名是一个指针,但它是一个指针常量,也就是说不带下标的数组名不能作为左值。指针数组的声明格式是:

指针类型 *数组名[常量表达式]

指针除了在数组中应用广泛,在函数中应用的也广泛,在某些情况下,将指针作为函数的参数或函数的返回值回给我们的应用带来很大的方便。向函数传递数组是将指针作为参数的特殊形式。由于指针可以直接操作内存中的数据,所以它可以用来修改实参。这个功能与引用类似。指针虽然和应用虽然都能够修实参,但是指针更加危险,应为应用仅限于修改某一个确定的参数,而指针却可以修改内存中的人一个参据,通过间接引用指针就可以在一个函数内修改函数外甚至系统中的数据。为了避免指针作为函数参数导致数据被意外修改,可以使用const来保护指针指向的数据。数组的存储空间必须在程序运行前申请,即数组的大小在编译前必须是已知的常量表达式,空间申请得太大会造成浪费,空间申请得太小会造成数据溢出而使得程序异常。在C++中允许在程序运行时根据自己的需要申请一定的内存空间,这个申请的空间就是堆内存(Heap 空间)。在C++中可以用new来申请堆空间,其格式如下:

new  数据类型[表达式]

其中,表达式可以是一个整型正常变量,也可以是一个有确定值的整型变量,其作用类似声明数组时的元素个数,所以两旁的中括号不可省略。当一个程序运行完毕之后,它所使用的数据就不再需要,由于内存是有限的,所以原来占据内存空间也应该释放给别的程序使用,也就是说堆内存要有借有还。确认申请的堆内存空间不再使用后,可以使用delete操作符来释放堆内存空间,其语法格式为:

delete [] 指向堆内存首元素的指针

如果申请的是一个堆内存变量,则delete后的[]可以省略,如果申请的是一个堆内存数组,则不能省略[],否则会出现内存泄露。

再写一个小程序测试一下堆栈:

/*

* Copyright (c) 2011,菜鸟在行动之--C++学习日志

* All rights reserved.

* 

* 文件名称:main.cpp

* 文件标识:LESSON8-5-MAIN1

*     要:学习使用指针5 -- 关于动态内存的申请与释放

* 

* 当前版本:1.0

*     者:懒猫爱飞

* 完成日期:20110717

*

* 取代版本:无 

* 原作者  :无

* 完成日期:无

*/

 

#include <iostream.h>

 

 

/*

 * 函数名称:int main(void)

 * 函数功能:主函数

 * 入口参数:无

 * 出口参数:无

 *     注:无

*/

int main()

{

int size = 0;

float sum = 0;

int *heapArray = NULL;

 

cout << "请输入元素个数:" << endl;

cin >> size;

 

heapArray = new int[size];

cout << "请输入各个元素:" << endl;

            

for(int i=0; i<size; i++)

{

     cin >> heapArray;   // 将所输入的数存入数组

     sum += heapArray;

}

 

cout << "这些数的平均值是: " << sum/size << endl; // 计算所输入数的平均值

 

delete [size]heapArray;

 

return 0;

}

<?xml:namespace prefix = w />

 

 

 

 

 

8-2 运行结果

关于指针还有很多东西,然而这些东西只有在运用时才能体会的更加深切,好了,这节课就先学到这,以后随着学习的深入,继续探究。

好了,最后再吼一下懒猫的口号:

 

每天进步一点点,开心多一点^_^

 

PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
EE直播间
更多
我要评论
0
10
关闭 站长推荐上一条 /3 下一条