980 likes | 1.11k Views
C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲). 学习目标. . 掌握定义各种指针的方法,掌握指针的基本操作; 了解指针与数组的关系,掌握利用指针访问数组元素的方法; 了解指针与函数的关系,掌握利用指针传递数据参数和函数参数的方法; 了解引用的概念和定义各种引用的方法,掌握利用引用传递数据参数; 掌握动态空间的申请和释放的方法,会利用指针操纵动态空间。. 第一讲主要内容. 指针的概念 指针变量的定义 常值指针 指针的基本操作. . 指针变量的定义. — 定义格式: 类型修饰符 * 变量名 〖 = 指针表达式 〗;.
E N D
C++语言程序设计第六章指针、引用和动态空间管理(第一讲)C++语言程序设计第六章指针、引用和动态空间管理(第一讲)
学习目标 • 掌握定义各种指针的方法,掌握指针的基本操作; • 了解指针与数组的关系,掌握利用指针访问数组元素的方法; • 了解指针与函数的关系,掌握利用指针传递数据参数和函数参数的方法; • 了解引用的概念和定义各种引用的方法,掌握利用引用传递数据参数; • 掌握动态空间的申请和释放的方法,会利用指针操纵动态空间。
第一讲主要内容 指针的概念 指针变量的定义 常值指针 指针的基本操作
指针变量的定义.. • —定义格式: • 类型修饰符*变量名〖 =指针表达式〗; 例如:int *pn,*ph;double d,*pd1=&d,*pd2=pd1;char *s="This is a string";void *pd3=NULL,*pd4=0;long *pd5=NULL;
指针变量的定义 pd3 d pd1 pd4 pd2 pd5 s This is a string\0 图6-2指针图示方法示例
指针的概念 空指针:地址值为 0,专用于表示未指向任何数据;地址值 0 可用 NULL 表示; 无类型指针(void 指针):无类型限制的指针,可以用来指向任何类型的数据。
指针的基本操作.. —— 指针赋值:操作符 = 同类型指针之间可以互相赋值 任何类型的指针可赋值给void指针,但反过来却不行,例如:char c=’X’,*s; s=&c;void *p1,*p2=NULL;p1=s; //允许s=p2; //不允许
指针的基本操作.. —— 取变量的地址:操作符 &例如:int k,*p; p=&k; //p指向变量k上面两个语句可以合并成一个:int k,*p=&k; //p指向变量k
指针的基本操作.. —— 间接访问:操作符 * 通过1元操作符*可以存取指针所指向的数据,例如:int *pd,d; pd=&d; //使pd指向d *pd=99; cout<<*pd<<' '<<d; 程序输出99 99
指针的基本操作.. • * 和 & 是两个互逆的操作,当这两个操作符碰到一起时,其作用相互抵消,例如 *&k=3与k=3效果完全相同
常值指针.. • —含义之一:所指向的数据为常值 • 定义这样指针时须将 const 放在 * 号之前,例如:const char *s="Hello!"; 或char const *s="Hello!";
常值指针.. 定义这样指针时不必初始化,如:const char *s; s="Hello!"; s 所指向的数据不可改变,但 s 本身可改变,例如:s="Hi!"; //正确! *s='Y'; //错误!
常值指针.. —— 含义之二:指针本身为常值 定义这样指针须将 const 放在变量名之前,而且必须初始化。如:char * const s="Hello!"; s 本身不可改变,但所指向的数据可以改变,例如:s="Hi!"; //错误! *s='Y'; //正确!
常值指针 —常值也可以是上述两种含义的综合,如:const char * const s="Hello!";或char const * const s="Hello!";
指针的基本操作.. —— 判断一指针是否是空指针:操作符 == 和 != “如果p是空指针,则...”if(p==0)...if(p==NULL)...if(!p)... // C++风格
指针的基本操作.. “如果p不是空指针,则...”if(p!=0)...if(p!=NULL)...if(p)... // C++风格 也可利用 > < >= <= 等操作符比较两个指针的大小,但很少用到。
指针的基本操作.. —— 计算两地址间数据单元的个数:操作符 – 同类型的两指针相减,其结果是一个整数,表示两地址之间可容纳的相应类型数据的个数,例如:int n,m[12],*p1=&m[5],*p2=&m[10];n=p2-p1; //n==5
指针的基本操作.. 0 1 2 3 4 5 6 7 8 9 10 11 m p1 p2
指针的基本操作.. ——指针移动:移动 n 个单位 格式:指针表达式+ n 指针变量+= n指针表达式- n 指针变量-= n 移动的实际字节数= n*sizeof(指针的类型)
指针的基本操作.. • ——指针移动:移动 1 个单位 • 格式:++指针变量指针变量++--指针变量指针变量--执行int k,*pk=&k; cout<<endl<<++pk; cout<<endl<<pk;显示的是两个相同的地址
指针的基本操作... 执行int k,*pk=&k; cout<<endl<<pk++; cout<<endl<<pk;显示的是两个不同的地址 —— 指针表达式也有与数值表达式类似的副作用问题
指针的基本操作.. —— 指针类型的强制转换 格式:(类型修饰符 *)指针表达式 举例:short i=258; //00000001 00000010char *p=(char *)&i;cout<<endl<<int(*p)<<int(*(p+1));输出是:21
指针的基本操作.. —— 正确理解下列组合操作的含义: *p++ (*p)++ *++p ++*p
初始状态: d p 执行 *p++ 后: (*p++的值:3) d p 3 3 6 6 9 9 指针的基本操作.. • *p++:取 p 所指向单元的数据作为表达式的值,然后使 p 指向下一个单元;
初始状态: d p 执行( *p)++ 后: ((*p)++的值:3) d p 4 3 6 6 9 9 指针的基本操作.. • (*p)++:取p所指向单元的数据作为表达式的值,然后使该单元的数据值增1;
初始状态: d p 执行 * ++ p后: (* ++ p的值:6) d p 3 3 6 6 9 9 指针的基本操作.. • *++p:使p指向下一个单元,然后取该单元的数据作为表达式的值;
初始状态: d p 执行++ *p后: ( ++ *p的值:4) d p 4 3 6 6 9 9 指针的基本操作.. • ++*p:将p所指向单元的数据值增1并作为表达式的值。
C++语言程序设计第六章指针、引用和动态空间管理(第二讲)C++语言程序设计第六章指针、引用和动态空间管理(第二讲)
第二讲主要内容 数组的指针访问方式 关于“指向数组的指针” 字符指针与字符串 指针数组 数组参数
数组的指针访问方式.. • ——一维数组元素的指针访问方式 • 一维数组名是指向该数组首元素的的常值指针 • A[i] ←→ *(A+i) • A[0] ←→ *(A+0) ←→ *A • int s[]={0,1,2,3,4,5},*p=s; cout<< *p << p[1] << *(p+2) << s[3] << p[4] << *(s+5);
数组的指针访问方式 • —— 二维数组元素的指针访问方式 • 一维数组的情况可以推广到二维数组和更多维的数组: • 二维数组名是指向该数组首行一维数组的一根指针B[i][j] *(B[i]+j) ↓ ↑A[j] ←→ *(A+j) • 因此: B[i][j] ←→ *(B[i]+j) ←→ *(*(B+i)+j)
数组的指针访问方式.. • 当i、j之一为0或均为0时: • B[i][0] ←→ *(B[i]+0) ←→ *B[i]←→ **(B+i) • B[0][j] ←→ (*(B+0))[j]←→ (*B)[j]←→ *(*B+j) • B[0][0] ←→ *(B[0]+0)←→ *B[0]←→ **(B+0)←→ **B
数组的指针访问方式.. • —— 数组的下标操作就是一种特定形式的指针操作:A[i]是 *(A+i)的另一种表示形式。
关于“指向数组的指针”.. • —— 一维数组的例子: • int s[5];int (*ps1)[5]=&s; int *ps2=s; //或 =&s[0];
ps1 (&s) ps2 (s 或 &s[0]) 关于“指向数组的指针”..
关于“指向数组的指针”.. • —— 二维数组的例子: • int w[3][4];int (*p1)[3][4]=&w; int (*p2)[4]=w; //或 =&w[0]; • int *p3=w[0]; //或 =&w[0][0];
关于“指向数组的指针”.. p1 (&w) p2 (w 或 &w[0]) p3 (w[0] 或 &w[0][0])
关于“指向数组的指针”.. • —— 直接计算数组单元地址二维数组 i 行 j 列单元地址=首元素地址+i×列数+j • 例6.1:设计函数show_matrix,它显示参数传来的任意规格的整型二维数组。
关于“指向数组的指针”.. • 1:#include<iomanip.h> • 2: • 3:void show_matrix(int *Array, int row,int col,int width){ • …… • 7: for(int i=0;i<row;i++){ • 8: cout<<endl; • 9: for(int j=0;j<col;j++) cout<<setw(width) <<*(Array+i*col+j); • 10: } • 11:}
关于“指向数组的指针” 也可以是: &s[0][0] • 12: • 13:void main(){ • 14: int s[][3]={{ 1, 2, 3}, { 4, 5, 6}, { 7, 8, 9}, {10,11,12}}; • 15: show_matrix(s[0],4,3,5); • 16: cout<<endl; • 17:}
字符指针与字符串.. • —— 程序中的字符串常量就是指向该字符串的指针,例如: • char *p="string"; • 或 • char *p; • P="string";
字符指针与字符串.. ——(a) char *p="string"; 和(b) char p[]="string";的区别 (b)是p[]={'s','t','r','i','n','g','\0'};的简略表示形式,(a)没有类似的表示形式
字符指针与字符串.. • (a)中的字符串存储于静态数据区,(b)中的字符串的存储特性由相应的变量决定,可以是静态的或自动的 • (a)中的字符串一般不应改变
字符指针与字符串.. • ——例6.2 设计函数 STRLEN,模拟标准函数 strlen。 • int STRLEN(const char *d) • { • int p=0; • while( *d++ ) p++; • return p; • }
字符指针与字符串.. • —— 例6.3 设计函数STRCAT,模拟标准函数 strcat。 • char *STRCAT(char *s, const char *d) • { • char *p=s; • while(*p) p++; • do *p++=*d; while(*d++); • return s; • }
指针数组.. • —— 若数组的每个元素是一个指针,则称为指针数组,例如: • int *ip[10];double *dp[5][8]; • int a,b,c,d; • int *s[]={&a,&b,&c,&d};
指针数组.. • —— 指针数组应用:构造字符串符号表 • 例如:char *MONTH[]={ NULL,"January","Feburay", "March","April","May","June", "July", "August","September", "October","November","December"};
指针数组.. 命令行参数的个数(至少是1) 存放命令行参数的“符号表” • —— 指针数组应用:获取命令行参数信息 • 命令行参数实例:C:\>attrib +r readme.txt • 主函数形参的含义:int main(int argc, char *argv[])
指针数组.. • argv[0] 指向被运行程序的全路径程序文件名。 • argv[1] 指向命令行程序名后的第一个字符串。 • argv[2] 指向命令行程序名后的第二个字符串。 • …… • argv[argc-1] 指向命令行程序名后的最后一个字符串。 • argv[argc] 空指针(NULL)。