第五章 指针 5.1 指针的概念 5.2 指针与数组 5.3 字符串指针.

Slides:



Advertisements
Similar presentations
程序设计导论 ——第15讲 结构与结构数组.
Advertisements

程序设计导论 结构与结构数组.
第九章 指针 西安工程大学.
第七章 指针 计算机公共教学部.
第六章 指针 指针的概念 指针变量 指针与数组 指针与函数 返回指针值的函数.
第7章 指针 存储地址的变量的类型就是指针类型 能直接对内存地址操作, 实现动态存储管理 容易产生副作用, 初学者常会出错
二级指针与二维数组.
C语言程序设计基础 第10章 指针进阶 刘新国.
10.1 二级指针 10.2 指针与二维数组 10.3 指针的动态存储分配 10.4 函数指针 10.5 main函数的参数
第 6 章 第 6 章 指 针 指 针 1.
第6章 指针 6.1 指针的概念 6.2 变量与指针 6.3 数组与指针 6.4 字符串与指针 6.5 函数与指针 6.6 返回指针值的函数
6.4 字符串与指针 1. 用字符数组存放一个字符串.
第六节 二维数组和指针 二维数组的地址 对于一维数组: (1)数组名array表示数组的首地址, 即array[0]的地址;
8.1 指针的概念 8.2 指针变量 8.3 指针变量的基础类型 8.4 指针的运算 8.5 指针与一维数组 8.6 指针应用实例
C++中的声音处理 在传统Turbo C环境中,如果想用C语言控制电脑发声,可以用Sound函数。在VC6.6环境中如果想控制电脑发声则采用Beep函数。原型为: Beep(频率,持续时间) , 单位毫秒 暂停程序执行使用Sleep函数 Sleep(持续时间), 单位毫秒 引用这两个函数时,必须包含头文件
C++程序设计 王希 图书馆三楼办公室.
Using C++ The Weird Way Something about c++11 & OOP tricks
指 针 为什么要使用指针 指针变量 指针与数组 返回指针值的函数 动态内存分配 通过指针引用字符串 指向函数的指针 小 结 习 题.
資料大樓 --談指標與陣列 綠園.
第九章 结构体 主讲教师 :贾月乐 电话:
第 十 章 指 针.
C语言高级编程(第四部分) 字符串 北京大学 信息科学技术学院.
C++语言程序设计 C++语言程序设计 第六章 指针和引用 第十一组 C++语言程序设计.
第五章 指针 5.1 指针的概念和定义 5.2 指针运算 5.3 指针和数组 5.4 字符串指针 5.5 指针数组 5.6 指向指针的指针
二维数组的指针表示 与复杂的指针例子 专题研讨课之三.
第一单元 初识C程序与C程序开发平台搭建 ---观其大略
第3讲 C++程序控制结构 3.1 顺序结构 3.2 分支结构 3.3 循环结构 3.4 转向控制 3.5 综合案例分析.
C++程序设计 string(字符串类) vector(容器类).
C++语言程序设计 C++语言程序设计 第六章 指针和引用 第十一组 C++语言程序设计.
第8章 指针.
程序的三种基本结构 if条件分支语句 switch多路开关语句 循环语句 循环嵌套 break,continue和goto语句
第六章 指针 指针的概念 指针的运算 指向变量的指针 指向数组的指针 指向函数的指针 二级指针 主讲:李祥 时间:2015年10月.
C++语言程序设计 C++语言程序设计 第六章 指针和引用 第十一组 C++语言程序设计.
切換Dev c++顯示語言 工具->環境選項(V)->介面->language (Chinese TW)
欲穷千里,更上层楼 第十章 指 针 指针是C语言中广泛使用的一种数据类型。 运用指针编程是C语言最主要的风格之一。利用指针变量可以表示各种数据结构; 能很方便地使用数组和字符串; 并能象汇编语言一样处理内存地址,从而编出精练而高效的程序。指针极大地丰富了C语言的功能。 学习指针是学习C语言中最重要的一环,
第五章 习题课 电子信息与计算机科学系 曾庆尚.
C++大学基础教程 第6章 指针和引用 北京科技大学 信息基础科学系.
9.1 地址、指针和变量 9.2 指针运算 9.3 指针与数组 9.4 函数与指针 9.5 程序综合举例 9.6 上机实训.
C++语言程序设计 C++语言程序设计 第七章 类与对象 第十一组 C++语言程序设计.
C++语言程序设计 C++语言程序设计 第六章 指针和引用 第十一组 C++语言程序设计.
C++语言程序设计 C++语言程序设计 第三章 控制语句 第十一组 C++语言程序设计.
C语言大学实用教程 第7章 指针 西南财经大学经济信息工程学院 刘家芬
第二章 Java基本语法 讲师:复凡.
指针 几个概念:  指针也是一种数据类型,具有指针类型的变量,称为指针变量。
C++语言程序设计 C++语言程序设计 第六章 指针和引用 第十一组 C++语言程序设计.
物件導向程式設計 CH2.
第6讲 指针与引用 6.1 指针 6.2 引用.
<编程达人入门课程> 本节内容 内存的使用 视频提供:昆山爱达人信息技术有限公司 官网地址: 联系QQ: QQ交流群: ,
C语言程序设计 第一章 数据类型, 运算符与表达式 第二章 顺序程序设计 第三章 选择结构程序设计 第四章 循环控制 第五章 数组.
第6章 指针 6.1 指针的概念 6.2 变量与指针 6.3 数组与指针 6.4 字符串与指针 6.5 函数与指针 6.6 返回指针值的函数
<编程达人入门课程> 本节内容 字符与字符串 视频提供:昆山爱达人信息技术有限公司 官网地址: 联系QQ: QQ交流群: ,
C++程式設計入門 變數與運算子 作者:黃建庭.
第九节 赋值运算符和赋值表达式.
3.16 枚举算法及其程序实现 ——数组的作用.
本节内容 结构体 视频提供:昆山爱达人信息技术有限公司 官网地址: 联系QQ: QQ交流群 : 联系电话:
第五章 数组与指针 1 数组的简单操作 2 数组与指针 3 字符数组与字符串 4 字符串处理函数 5 数组应用举例.
C++语言程序设计 C++语言程序设计 第六章 指针和引用 第十一组 C++语言程序设计.
C/C++基礎程式設計班 C++: 物件的使用、參考、重載函式 講師:林業峻 CSIE, NTU 3/28, 2015.
2.6 字符型数据 一、 字符常量 1、字符常量的定义 用一对单引号括起来的单个字符,称为字符常量。 例如,‘A’、‘1’、‘+’等。
本节内容 结构体.
本节内容 指针类型的使用 视频提供:昆山爱达人信息技术有限公司.
C++语言程序设计 C++语言程序设计 第十章 多态 第十一组 C++语言程序设计.
C++语言程序设计 C++语言程序设计 第一章 C++语言概述 第十一组 C++语言程序设计.
C语言程序设计 第8章 指针.
C++语言程序设计 C++语言程序设计 第九章 类的特殊成员 第十一组 C++语言程序设计.
第八章 指 针 北京邮电大学出版社.
變數與資料型態  綠園.
第7章 地址和指针 7.1 地址和指针的概念 7.2 指针变量的定义和指针变量的基类型 7.3 给指针变量赋值 7.4 对指针变量的操作
C++语言程序设计 C++语言程序设计 第二章 基本数据类型与表达式 第十一组 C++语言程序设计.
Presentation transcript:

第五章 指针 5.1 指针的概念 5.2 指针与数组 5.3 字符串指针

5.1 指针的概念 地下工作者阿金接到上级指令,要去寻找打开密电码的密钥,这是一个整数。几经周折,才探知如下线索:密钥藏在一栋三年前就被贴上封条的小楼中。 一个风雨交加的夜晚,阿金潜入了小楼,房间很多,不知该进哪一间,正在一筹莫展之际,忽然走廊上的电话铃声响起。艺高人胆大,阿金毫不迟疑,抓起听筒,只听一个陌生人说:“去打开3010房间,那里有线索”。阿金疾步上楼,打开3010房间,用电筒一照,只见桌上赫然6个大字:“地址2000”。阿金眼睛一亮,迅速找到2000房间,取出重要数据98,完成了任务。

5.1 指针的概念 如果我们将房间看作计算机的内存单元,那么,房间的编号就是内存单元的地址,存放地址的内存单元就对应程序中的变量,这类特殊的变量在C中称指针变量。这里,pointer是指针变量,2000是pointer指针变量的值

5.1 指针的概念 1、数据藏在一个内存地址单元中,地址是2000。 2、地址2000又由pointer单元所指认,pointer单元的地址为3010。 3、98的直接地址是2000;98的间接地址是3010;3010中存的是直接地址2000。 4、称pointer为指针变量,2000是指针变量的值,实际上是有用数据藏在存储器中的地址。

5.1 指针的概念 指针的定义及初始化: int *pointer = 0 ; 指针:就是地址,一个变量的指针就是该变量的地址。 指针变量:专门存放地址的一类特殊的变量。 int *pointer = 0 ; 上面的语句定义了一个名为pointer的指针,且被初始化为0,该指针“指向”的目标类型为整型。 在定义指针时,将其初始化为0是一个好办法。

指针变量的常见类型 简单的指针变量分为: int *p, *q; // 定义p,q为指向整数类型变量的指针 float *point; // point为指向float型变量的指针 double *pd; // 定义pd为指向double型变量的指针 int (*pa)[10];// 定义pa为指向int型数组的指针 int **qq; // 定义qq为指向int型指针的指针 StudentInfo *pStu; // 定义指向结构的指针pStu

5.1 指针的概念 int *pointer = 0 ; 指针是一种特殊的变量,特殊性表现在类型和值上。 从变量讲,指针也具有变量的三个要素: (1)变量名,这与一般变量取名相同,由英文字符开始。 (2)指针变量的类型,是指针所指向的变量的类型,而不是自身的类型。 (3)指针的值是某个变量的内存地址。 从上面的概念可知,指针本身类型是int型,因为任何内存地址都是整型的。但是指针变量的类型却定义成它所指向的变量的类型。 int *pointer = 0 ;

5.1 指针的概念 指针的赋值: 1、使用取地址运算符(&)将变量的地址取出赋给指针变量 int i, j; int *i_pointer = 0; i_pointer = &i; 2000 执行以上变量赋值语句后, i_pointer 就指向了变量 i 代表的内存单元。

5.1 指针的概念 指针的赋值(续): 2、将一个已有具体指向的指针变量赋值给另一个指针变量。 int i = 123; int *p1 = 0 , *p2 = 0; p1 = &i ; p2 = p1; 执行以上变量赋值语句后, p1、p2 就指向了相同的内存单元。

5.1 指针的概念 变量(内存)的访问方式: ①直接访问:通过变量名访问。 i = 98; cout<<"i="<<i<<endl; ②间接访问:使用间接访问运算符(*),通过指针变量中存放的值,找到最终要访问的变量。 *i_pointer = 98; cout<<"i="<< *i_pointer <<endl;

有关指针变量的说明 ① 一个指针变量可以指向任何一个同类型的普通变量;但是, 在某一个时刻,它只能指向某一个同类型的变量 int *pa, *pb, a, b; pa = &a; pb = &b; pa = &b; pb = &a; ② 让指针变量指向某个同类型普通变量的方法是:把该普通 变量的地址保存到指针变量中。 ③ 必须对指针变量进行了正确合法的初始化后,才能使用该 指针变量访问它所指向的内存单元。没有具体指向的指针变量叫悬空指针,对它所指向的内存单元的使用是非法的。 int *pa, *pb, a, b; *pa = 100; 或 cout<<"*pa="<<*pa<<endl;

有关指针变量的说明 ④ 即使对指针变量进行了正确合法的初始化后,也只能用该 指针变量访问合法的允许访问的内存单元。不能使用该指针 变量去随意访问其它不确定的内存单元,否则,结果是不可 预料的。 int *pa, *pb, a, b; pa = &a; *pa = 100; pb = &b; *pb = 200; cout<<"value after a = "<<*(pa + 1)<<endl; Cout<<"value after b = "<<*(pb + 1)<<endl; *(pa + 1) = 1000; *(pb + 1) = 2000; 正确安全使用指针变量 错误使用指针变量 错误使用指针变量而且可能很危险

有关运算符*和&的说明 ① 假设有 int a, *pa; pa = &a; 则: &*pa 相当于 &a,因为 *pa 就相当于 a 由于 ++ 和 * 为同一运算级别,则根据结合性, *pa ++ 相当于*(pa ++) ,与(*pa) ++是完全不同的。 *(pa ++) :先得到pa当前指向的单元的值,再使pa自增 (*pa) ++ :是pa所指向的单元的值自增 pa 100 200 *(pa ++) :得到100,pa自增 (*pa) ++ :得到100,pa所指 向的单元变成101,而pa不变

5.2 指针和数组 5.2.1 指针与一维数组 数组的首地址也就是数组中第1个(下标0)元素的地址; 在内存中数组的元素的地址是连续递增的; 5.2.1 指针与一维数组 数组的首地址也就是数组中第1个(下标0)元素的地址; 在内存中数组的元素的地址是连续递增的; 通过数组的首地址,加上偏移量就可以依次得到其它元素的地址; &score[0]+偏移量 -> &score[1] 这里的偏移量就是一个数组元素所占的字节数。编译程序会根据数组元素的类型,自动确定出不同的偏移量

5.2 指针与数组 5.2.1 使用指针访问数组元素 #include <iostream> //预编译命令 using namespace std; int main() //主函数 { //函数体开始 int a[5]={1,3,5,7,9};//定义数组,赋初值 int *p=NULL; //定义指针变量 int i; //定义整型变量 p=a; //赋值给指针变量,让p指向a数组for(i=0;i<5;i=i+1) { //循环体开始 cout<<"a["<<i<<"]="<<*p<<endl; //输出a数组元素的值 p=p+1; //指针变量加1 } //循环体结束 return 0; } //函数体结束

*p a[0] *(p+1) a[1] *(p+2) a[2] *(p+3) a[3] *(p+4) a[4] 说明 (1) p=a; 这里数组名作为数组的起始地址,即a[0]的地址。因此 p=a 等效于 p=&a[0]; (2) p=p+1; 如p指向a[0], 则p=p+1之后,p指向a[1] (3) 如果p=a 等效于 p=&a[0]; 则 p=a+4 等效于 p=&a[4]; *p *(p+1) *(p+2) *(p+3) *(p+4) a[0] a[1] a[2] a[3] a[4] p p 等效 等效 等效 p+1 p+1 p+2 p+2

做下面的实验 #include <iostream> // 预编译命令 using namespace std; int main() // 主函数 { // 函数体开始 int a[5]={1,3,5,7,9}; // 定义数组,赋初值 int *p=NULL; // 定义指针变量 int i=0; // 定义整型变量,赋初值 for(p=a;p<a+5;p=p+1) // 让p指向a数组 { // 循环体开始 cout<<"a["<<i<<"]="<<*p<<endl; // 输出a数组元素的值 i=i+1; // 让i加1 } // 循环体结束 return 0; } // 函数体结束

5.2.2 数组名是一个常量指针,指向该数组的首地址. #include <iostream> using namespace std; int main() { char *p; // 定义指向字符类型的指针变量p char s[] = "abcdefgh";// 定义字符数组,并赋值 p=s; // 数组名是一个常量指针, // 它指向该数组首地址 while(*p != '\0') // 当p所指向的元素不为'\0'时 p=p+1; // 让指针加1 } cout<<"字符串长度为"<<p-s<<endl; return 0;

1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 s a b c d e f g h \0 a b c d e f g h \0 a b c d e f g h \0 p p p p p p p p p s 图中数组的首地址是s[0]的地址,即&s[0]。s可看作是指向s[0]的指针。s是不会动的,是常量指针。 P是指针变量,其值可以改变 执行p=p+1后,p后移一格,指向s[1] 至p指向'\0'为止

#include <iostream> using namespace std; int main() { 数组名是一个常量指针,指向该数组的首地址 #include <iostream> using namespace std; int main() { char shuzi[]="987654321";//定义数组, // 赋初值为数字字符串 char *p=&shuzi[8];// 让p指向shuzi[8]元素, // 该处是字符‘1’ for(;p>=shuzi;p--)// 当p>=shuzi时循环 cout<<*p; // 输出一个由p指向的字符 cout<<endl; // 换行 return 0; }

shuzi 9 8 7 6 5 4 3 2 1 \0 1 2 3 4 5 6 7 8 9 p p p p p p p p p p 说明: 1、字符串: 数字字符串。 2、p指向shuzi[8],即指向串中的字符’1’。 3、直到型循环,用putchar函数将shuzi[8]输出到屏幕;之后让p=p-1。 4、在while中,当p>=shuzi则继续执行循环体。一旦 p<shuzi 则退出循环。这种做法使输出结果为 123456789 5、在本例中数组名shuzi是一个常量指针,永远指向shuzi[0]的地址上。 思考:如何通过p和shuzi求该数字字符串的长度

5.2.3 指针数组 1. 指针数组的概念 指针数组也是数组,但它的各数组元素都是指针,且必须是指向同一种数据类型的指针。 2. 指针数组的定义和初始化 假设存在3个数组,定义如下 int ar0[]={0,1,2}; int ar1[]={1,2,3}; int ar2[]={2,3,4}; 下面的语句定义一个指针数组p,并初始化 int *p[]={ar0,ar1,ar2};

5.2.5 指针与结构 StudentInfo *pStuInfo = 0; StudentInfo stu; struct StudentInfo { char no[20]; int sexy; double height; Date birthday; }; 5.2.5 指针与结构 图5-3-6 指向结构的指针 … &stu.sexy 数据区 地址 结构成员 pStuInfo stu.no[0] stu.sexy &stu stu.no &stu.height &stu.birthday stu.birthday.year StudentInfo stu; StudentInfo *pStuInfo = 0; pStuInfo = &stu; 引用结构变量stu的成员: stu.no = "1443011101"; (*pStuInfo).no = "1443011101"; pStuInfo -> no = "1443011101";

输入 学生 信息 const int STU_NUM = 20; // 学生人数 StudentInfo stu[STU_NUM+1]; // 下标i处存储第i位同学的信息,stu[0]不使用 StudentInfo *p_stuInfo = 0; // 指向学生信息的指针,初始化为0 int i = 0, j = 0; // 循环变量 int changed = 0; // 交换标志 p_stuInfo = stu+1; //p_stuInfo指向stu[1] for(; p_stuInfo <= stu+STU_NUM; p_stuInfo++) { *p_stuInfo = readStudent(); // 输入当前学生信息 } 输入 学生 信息

按 身 高 排 序 p_stuInfo = stu; //p_stuInfo指向结构数组的开始 for(i =1; i < STU_NUM; i++) // 扫描n-1遍 { changed = 0; // 置交换标志为,表示未交换 for(j=1; j <= STU_NUM-i; j++) { // 每遍比较n-i次 if((p_stuInfo[j].height) > (p_stuInfo[j+1].height)) {// 交换stu[j]和stu[j+1] stu[0] = p_stuInfo[j]; p_stuInfo[j] = p_stuInfo[j+1]; p_stuInfo[j+1] = stu[0]; changed = 1; // 置交换标志为1 } if(changed == 0) {// 如果本遍排序中未交换,则退出循环 break; 按 身 高 排 序

输出排序后学生信息 cout << endl << "输入的学生信息为(按身高升序排列):" << endl; for(p_stuInfo++; p_stuInfo <= stu+STU_NUM; p_stuInfo++) { writeStudent(*p_stuInfo); // 依次输出个人信息 }

5.3 字符串指针 可以使用指针指向字符数组或字符串常量,通过指针来使用字符数组或字符串常量。 指向字符串的指针变量实际上就是一个指向字符型变量的指针变量,正如同指向整型数组的指针变量就是指向一个整型变量的指针变量一样,因为一个字符串就是一个字符数组。 指向字符串的指针变量,它保存的是字符串中第一个字符所在内存单元的地址。

通过指针变量访问字符串 能够通过指针变量访问字符串的前提是:已经定义了一个字符型指针变量,并且已经把某个字符串的指针赋值给它。 访问方法: 指针法或下标法 如果pstr的初值为字符串的第一个字符的地址,比如有 char *pstr = "Hello, World"; 则有以下事实: ① pstr + i 就是第 i 个字符的地址,即它指向字符串中的第 i 个字符 ② *(pstr + i) 或者 pstr[i] 就是它所指向的字符 ③ 指针变量也可以使用下标法,即 pstr[i] 和*(pstr + i) 是等价的

通过指针变量引用数组元素: ◆ 编程把字符串s2复制到字符串s1中 /* 方法1:用数组名和下标 */ #include <iostream> using namespace std; int main( ) { char s1[80] = "", s2[ ] = "hello, world"; int n; for(n = 0; s2[n] != '\0'; n ++) s1[n] = s2[n]; s1[n] = '\0'; cout<<"s1="<<s1<<"\ns2="<<s2<<endl; return 0; }

通过指针变量引用数组元素: ◆ 编程把字符串s2复制到字符串s1中 /* 方法2:用数组名+偏移量得到元素地址,访问元素*/ #include <iostream> using namespace std; int main( ) { char s1[80] = "", s2[ ] = "hello, world"; int n; for(n = 0; s2[n] != '\0'; n ++) *(s1 + n) = *(s2 + n); *(s1 + n) = '\0'; cout<<"s1="<<s1<<"\ns2="<<s2<<endl; return 0; } 特点: 数组名本身不变也不可能被改变

通过指针变量引用数组元素: ◆ 编程把字符串s2复制到字符串s1中 /* 方法3:用指针变量+偏移量得到元素地址,访问元素*/ #include <iostream> using namespace std; int main( ) { char s1[80] = "", s2[ ] = "hello, world"; int n; char *p1 = s1, *p2 = s2; for(n = 0; *(p2 + n) != '\0'; n ++) *(p1 + n) = *(p2 + n); *(p1 + n) = '\0'; cout<<"s1="<<s1<<"\ns2="<<s2<<endl; return 0; } 特点: 指针变量本身的值没有变化

通过指针变量引用数组元素: ◆ 编程把字符串s2复制到字符串s1中 /* 方法4:用指针变量自身变化得到元素地址,访问元素*/ #include <iostream> using namespace std; int main( ) { char s1[80] = "", s2[ ] = "hello, world"; int n; char *p1 = s1, *p2 = s2; for(n = 0; *p2 != '\0'; n ++) *(p1 ++) = *(p2 ++); *p1 = '\0'; cout<<"s1="<<s1<<"\ns2="<<s2<<endl; return 0; } 特点: 普通变量做循环控制变量

通过指针变量引用数组元素: ◆ 编程把字符串s2复制到字符串s1中 /* 方法5:用指针变量自身变化得到元素地址,访问元素 */ #include <iostream> using namespace std; int main( ) { char s1[80] = "", s2[ ] = "hello, world"; char *p1 = s1, *p2 = s2; for( ; *p2 != '\0'; p1 ++, p2 ++) *p1 = *p2; *p1 = '\0'; cout<<"s1="<<s1<<"\ns2="<<s2<<endl; return 0; } 特点: 指针变量做循环控制变量

指向字符串的指针变量的有关运算 如有: char str[80], *ps; ps = str; 或 ps = &str[0]; ① ps ++ 或 ps += 1,是下一个字符的地址(即 ps 指 向下一个字符) ps -- 或 ps -= 1,是上一个字符的地址(即 ps 指向 上一个字符) ② * ps ++ 等价于 *(ps ++) ,即先得到 ps 当前指向 的字符,然后再使 ps 自增,从而指向下一个字符 ③ * ++ ps 等价于 *(++ ps) ,即先使 ps 自增,指向 下一个字符,然后得到 ps 所指向的字符 ④ (* ps) ++ ,则是表示 ps 当前指向的字符加1