1.34k likes | 1.54k Views
第 8 章 指针. 8.1 指针概念 8.2 指针运算 8.3 指针与数组 8.4 堆内存分配 8.5 const 指针. 8.6 指针与函数 8.7 字符指针 8.8 指针数组 8.9 函数指针 8.10 命令行参数 8.11 指针数据小结. 2. 8.1 指针概念. 1. 地址与指针. 程序的每一个对象,都在内存占有一块可标识的存储区域 每一块区域由若干字节组成 内存的每一个字节都有一个“地址” 一个对象的“地址”是指占有区域的第一个字节地址. 1010. 3. a. 1012. 4. b. 1014.
E N D
第 8 章 指针 8.1指针概念 8.2指针运算 8.3指针与数组 8.4堆内存分配 8.5 const 指针 8.6指针与函数 8.7字符指针 8.8指针数组 8.9函数指针 8.10命令行参数 8.11指针数据小结
2 8.1 指针概念 1. 地址与指针 程序的每一个对象,都在内存占有一块可标识的存储区域 每一块区域由若干字节组成 内存的每一个字节都有一个“地址” 一个对象的“地址”是指占有区域的第一个字节地址
1010 3 a 1012 4 b 1014 c 4.5 1018 d 8.6 x e 1022 y f 1023 3 1. 地址与指针 例:有以下说明语句: int a = 3 , b = 4 ; float c = 4.5 ; d = 8.6 ; char e = ‘x’ ; f = ‘y’ ;
4 1. 地址与指针 直接访问 通过名字或地址访问对象 例:scanf ( “%d%d%d”, &a, &b, &c ) ; a = a + b + c ; 间接访问 把对象的地址放在另一个变量中,通过这个变量访问对象
pa a &a 3 1010 3 a pa 1010 2002 pb b 1012 4 pb b 2004` 1012 &b 4 1014 pc 2006 c c 4.5 &c 4.5 2008 pc 1014 pd d 1018 1018 pd 2010 &d 8.6 d 8.6 2012 pe 1022 pe e &e x x e 1022 2014 1023 pf y f 1023 pf f &f y 5 1. 地址与指针
6 1. 地址与指针 指针 是地址。一个对象的指针就是该对象的地址 存放地址的变量称为 指针变量 通过指针变量可以间接访问对象
7 指针的类型 是它所指向的对象的类型 指针变量定义的一般形式为 类型 * 标识符 ; 注: “ * ” 表示该变量为指针变量 一个指针变量只能指向同一类型的对象 2. 指针类型与指针定义 例: int i ; // 整型变量 int * ip ; // 指向整型变量的指针变量 float * fp ; // 指向浮点型变量的指针变量 char * cp ; // 指向字符型变量的指针变量 const int * cip ; // 指向整常数的指针变量
ip 1000 ip i 3 . . . 3 i 1060 8 指针变量定义后,系统分配一个存放地址用的存储单元 要使指针变量指向一个对象,必须将对象的地址赋给指针变量 2. 指针类型与指针定义 例: int * ip , i = 3 ; ip = & i ; int * ip , i = 3 ;
ip 1000 ip i 3 . . . 3 i 1060 9 指针变量定义后,系统分配一个存放地址用的存储单元 要使指针变量指向一个对象,必须将对象的地址赋给指针变量 2. 指针类型与指针定义 例: int * ip , i = 3 ; ip = & i ; 1060 *ip & i ip = & i ;
ip 1000 ip i 3 . . . 3 i 1060 10 指针变量定义后,系统分配一个存放地址用的存储单元 要使指针变量指向一个对象,必须将对象的地址赋给指针变量 2. 指针类型与指针定义 例: int * ip , i = 3 ; ip = & i ; 1060 *ip & i
11 对指针变量常用操作: 给指针变量赋予地址值;输出指针变量的值;访问指针所指对象 等 3. 指针变量的引用 两个有关指针的运算符: &取地址运算符。&x 的值为x 的地址 *指针运算符(指向运算符,间接运算符)。* p 代表 p 所指对象 注意: “ * ”号在指针变量定义和程序执行语句中的区别 例: int i , * p ; // p是指向整型变量的指针 p = &i ; // 把变量 i 的地址赋给指针变量 p * p = 5 ; // 对 p所指变量赋值,等价于 i = 5 ; cout << i ; // 输出 i 的值 cout << * p ; // 输出 p 所指变量的值,与上一语句等价 Example8_1
输出 5 5 0x8fa9fff4 0x8fa9fff4 12 // Example 8_1 # include < iostream . h > main ( ) { int i , * p ; p = & i ; * p = 5 ; cout << i << endl ; cout << * p << endl ; cout << p << endl ; cout << & i << endl ; } 3. 指针变量的引用 Example8_2
p1 p2 p i1 10 i2 20 13 // Example8_2交换指针变量指向 # include <iostream.h> main () { int i1=10, i2 = 20, *p1, *p2, *p ; p1=&i1; p2=&i2; cout << “*p1=” << *p1 <<‘\t’ << “*p2=” << *p2 << endl ; p=p1; p1=p2; p2=p; cout << “*p1=” << *p1 << ‘\t’ << “*p2=” << *p2 << endl ; } 3. 指针变量的引用 int i1=10, i2 = 20, *p1, *p2, *p ;
p1 p2 p * p1 i1 10 * p2 i2 20 14 // Example8_2交换指针变量指向 # include <iostream.h> main () { int i1=10, i2 = 20, *p1, *p2, *p ; p1=&i1; p2=&i2; cout << “*p1=” << *p1 <<‘\t’ << “*p2=” << *p2 << endl ; p=p1; p1=p2; p2=p; cout << “*p1=” << *p1 << ‘\t’ << “*p2=” << *p2 << endl ; } 3. 指针变量的引用 p1=&i1; p2=&i2;
p1 p2 p * p1 i1 10 * p2 i2 20 15 // Example8_2交换指针变量指向 # include <iostream.h> main () { int i1=10, i2 = 20, *p1, *p2, *p ; p1=&i1; p2=&i2; cout << “*p1=” << *p1 <<‘\t’ << “*p2=” << *p2 << endl ; p=p1; p1=p2; p2=p; cout << “*p1=” << *p1 << ‘\t’ << “*p2=” << *p2 << endl ; } 3. 指针变量的引用 cout << “*p1=” << *p1 <<‘\t’ << “*p2=” << *p2 << endl ; 输出: *p1 = 10 *p2 = 20
p1 p2 p * p1 i1 10 * p2 i2 20 16 // Example8_2交换指针变量指向 # include <iostream.h> main () { int i1=10, i2 = 20, *p1, *p2, *p ; p1=&i1; p2=&i2; cout << “*p1=” << *p1 <<‘\t’ << “*p2=” << *p2 << endl ; p=p1; p1=p2; p2=p; cout << “*p1=” << *p1 << ‘\t’ << “*p2=” << *p2 << endl ; } * p 3. 指针变量的引用 p=p1; 输出: *p1 = 10 *p2 = 20
p1 p2 p * p1 i1 10 * p2 i2 20 17 // Example8_2交换指针变量指向 # include <iostream.h> main () { int i1=10, i2 = 20, *p1, *p2, *p ; p1=&i1; p2=&i2; cout << “*p1=” << *p1 <<‘\t’ << “*p2=” << *p2 << endl ; p=p1; p1=p2; p2=p; cout << “*p1=” << *p1 << ‘\t’ << “*p2=” << *p2 << endl ; } * p 3. 指针变量的引用 p1=p2; 输出: *p1 = 10 *p2 = 20
p1 p2 p i1 10 i2 20 18 // Example8_2交换指针变量指向 # include <iostream.h> main () { int i1=10, i2 = 20, *p1, *p2, *p ; p1=&i1; p2=&i2; cout << “*p1=” << *p1 <<‘\t’ << “*p2=” << *p2 << endl ; p=p1; p1=p2; p2=p; cout << “*p1=” << *p1 << ‘\t’ << “*p2=” << *p2 << endl ; } * p 3. 指针变量的引用 * p2 p1=p2; 输出: *p1 = 10 *p2 = 20
p1 p2 p i1 10 i2 20 19 // Example8_2交换指针变量指向 # include <iostream.h> main () { int i1=10, i2 = 20, *p1, *p2, *p ; p1=&i1; p2=&i2; cout << “*p1=” << *p1 <<‘\t’ << “*p2=” << *p2 << endl ; p=p1; p1=p2; p2=p; cout << “*p1=” << *p1 << ‘\t’ << “*p2=” << *p2 << endl ; } * p 3. 指针变量的引用 * p2 * p1 p1=p2; 输出: *p1 = 10 *p2 = 20
p1 p2 p i1 10 i2 20 20 // Example8_2交换指针变量指向 # include <iostream.h> main () { int i1=10, i2 = 20, *p1, *p2, *p ; p1=&i1; p2=&i2; cout << “*p1=” << *p1 <<‘\t’ << “*p2=” << *p2 << endl ; p=p1; p1=p2; p2=p; cout << “*p1=” << *p1 << ‘\t’ << “*p2=” << *p2 << endl ; } * p 3. 指针变量的引用 * p2 * p1 输出: p2=p; *p1 = 10 *p2 = 20
p1 p2 p i1 10 i2 20 21 // Example8_2交换指针变量指向 # include <iostream.h> main () { int i1=10, i2 = 20, *p1, *p2, *p ; p1=&i1; p2=&i2; cout << “*p1=” << *p1 <<‘\t’ << “*p2=” << *p2 << endl ; p=p1; p1=p2; p2=p; cout << “*p1=” << *p1 << ‘\t’ << “*p2=” << *p2 << endl ; } * p 3. 指针变量的引用 * p1 输出: p2=p; *p1 = 10 *p2 = 20
p1 p2 p i1 10 i2 20 22 // Example8_2交换指针变量指向 # include <iostream.h> main () { int i1=10, i2 = 20, *p1, *p2, *p ; p1=&i1; p2=&i2; cout << “*p1=” << *p1 <<‘\t’ << “*p2=” << *p2 << endl ; p=p1; p1=p2; p2=p; cout << “*p1=” << *p1 << ‘\t’ << “*p2=” << *p2 << endl ; } * p * p2 3. 指针变量的引用 * p1 输出: p2=p; *p1 = 10 *p2 = 20
p1 p2 p i1 10 i2 20 23 // Example8_2交换指针变量指向 # include <iostream.h> main () { int i1=10, i2 = 20, *p1, *p2, *p ; p1=&i1; p2=&i2; cout << “*p1=” << *p1 <<‘\t’ << “*p2=” << *p2 << endl ; p=p1; p1=p2; p2=p; cout << “*p1=” << *p1 << ‘\t’ << “*p2=” << *p2 << endl ; } * p * p2 3. 指针变量的引用 * p1 输出: cout << “*p1=” << *p1 <<‘\t’ << “*p2=” << *p2 << endl ; *p1 = 10 *p2 = 20 *p1 = 20 *p2 = 10 Example8_3
p1 p2 i1 10 i i2 20 24 // Example8_3交换指针所指变量的值 # include <iostream.h> main () { int i1=10, i2 = 20, i , *p1, *p2 ; p1=&i1; p2=&i2; cout << “*p1=” << *p1 <<‘\t’ << “*p2=” << *p2 << endl ; i=*p1; *p1=*p2; *p2=i; cout << “*p1=” << *p1 << ‘\t’ << “*p2=” << *p2 << endl ; } 3. 指针变量的引用 int i1=10, i2 = 20, i , *p1, *p2 ;
p1 p2 * p1 i1 10 i * p2 i2 20 25 // Example8_3交换指针所指变量的值 # include <iostream.h> main () { int i1=10, i2 = 20, i , *p1, *p2 ; p1=&i1; p2=&i2; cout << “*p1=” << *p1 <<‘\t’ << “*p2=” << *p2 << endl ; i=*p1; *p1=*p2; *p2=i; cout << “*p1=” << *p1 << ‘\t’ << “*p2=” << *p2 << endl ; } 3. 指针变量的引用 p1=&i1; p2=&i2;
p1 p2 * p1 i1 10 i * p2 i2 20 26 // Example8_3交换指针所指变量的值 # include <iostream.h> main () { int i1=10, i2 = 20, i , *p1, *p2 ; p1=&i1; p2=&i2; cout << “*p1=” << *p1 <<‘\t’ << “*p2=” << *p2 << endl ; i=*p1; *p1=*p2; *p2=i; cout << “*p1=” << *p1 << ‘\t’ << “*p2=” << *p2 << endl ; } 3. 指针变量的引用 cout << “*p1=” << *p1 <<‘\t’ << “*p2=” << *p2 << endl ; 输出: *p1 = 10 *p2 = 20
p1 p2 * p1 i1 10 i * p2 i2 20 27 // Example8_3交换指针所指变量的值 # include <iostream.h> main () { int i1=10, i2 = 20, i , *p1, *p2 ; p1=&i1; p2=&i2; cout << “*p1=” << *p1 <<‘\t’ << “*p2=” << *p2 << endl ; i=*p1; *p1=*p2; *p2=i; cout << “*p1=” << *p1 << ‘\t’ << “*p2=” << *p2 << endl ; } 3. 指针变量的引用 10 i=*p1; 输出: *p1 = 10 *p2 = 20
p1 p2 * p1 i1 10 i 10 * p2 i2 20 28 // Example8_3交换指针所指变量的值 # include <iostream.h> main () { int i1=10, i2 = 20, i , *p1, *p2 ; p1=&i1; p2=&i2; cout << “*p1=” << *p1 <<‘\t’ << “*p2=” << *p2 << endl ; i=*p1; *p1=*p2; *p2=i; cout << “*p1=” << *p1 << ‘\t’ << “*p2=” << *p2 << endl ; } 3. 指针变量的引用 20 *p1=*p2; 输出: *p1 = 10 *p2 = 20
p1 p2 * p1 i1 20 i 10 * p2 i2 20 29 // Example8_3交换指针所指变量的值 # include <iostream.h> main () { int i1=10, i2 = 20, i , *p1, *p2 ; p1=&i1; p2=&i2; cout << “*p1=” << *p1 <<‘\t’ << “*p2=” << *p2 << endl ; i=*p1; *p1=*p2; *p2=i; cout << “*p1=” << *p1 << ‘\t’ << “*p2=” << *p2 << endl ; } 3. 指针变量的引用 10 输出: *p2=i; *p1 = 10 *p2 = 20
p1 p2 * p1 i1 20 i 10 * p2 i2 10 30 // Example8_3交换指针所指变量的值 # include <iostream.h> main () { int i1=10, i2 = 20, i , *p1, *p2 ; p1=&i1; p2=&i2; cout << “*p1=” << *p1 <<‘\t’ << “*p2=” << *p2 << endl ; i=*p1; *p1=*p2; *p2=i; cout << “*p1=” << *p1 << ‘\t’ << “*p2=” << *p2 << endl ; } 3. 指针变量的引用 输出: cout << “*p1=” << *p1 <<‘\t’ << “*p2=” << *p2 << endl ; *p1 = 10 *p2 = 20 *p1 = 20 *p2 = 10
int **p1 int *p2 int i 3 &p2 &i 31 4.指针变量的地址 指针变量本身具有地址 一个指针变量也可以存放另一个指针变量的地址
32 定义“指向指针的指针” 类型 * * 指针变量名 4.指针变量的地址 例: int * * p ; 定义了一个二级指针变量 p , 它指向另一个指针变量 即存放另一个指向整型变量的指针的地址 等价于: int * ( * p ) ;
*p1 *p2 3 p1 p2 i 33 建立指针连接关系 4.指针变量的地址 例: int * * p1 ; int * p2 ; int i = 3 ; p2 = & i ; p1 = & p2 ; int * * p1 ; int * p2 ; &p2 &i int i = 3 ; p2 = & i ; p1 = & p2 ; p1 = & i ; // 错误,二级指针只能存放指针地址 cout << * i ;// 错误,i 不是指针
p3 p1 p4 p2 i 3 &p4 &p2 &p3 &i 34 从理论上,可以有多重指针 使用多重指针极易出错 一般使用二重指针就够了 // Example8_4 # include <iostream.h> main() { int ****p1, ***p2, **p3, *p4, i = 3 ; p1 = &p2; p2 = &p3; p3 = &p4; p4=&i; cout << ****p1 << endl ; } 4.指针变量的地址
35 8.2 指针运算 指针是一种数据类型,具有无符号整数值 指针值是地址,所以有特定的运算限制,只能进行: 与整数相加、减运算 同一数组中各元素地址间的关系运算与相减 赋值运算
1010 1022 1018 1010 ip 1012 fp 1014 1018 cp 1022 1023 36 1.指针与整数相加减 指针与整数相加、减,表示 指针在内存空间上下移动 移动以其指向对象类型长度为单位 ip + + 例: int * i p; float * fp ; char *cp ; :
1010 1022 1012 1018 ip 1012 fp 1014 1018 cp 1022 1023 37 1.指针与整数相加减 指针与整数相加、减,表示 指针在内存空间上下移动 移动以其指向对象类型长度为单位 fp-- 例: int * i p; float * fp ; char *cp ; :
1010 1022 1010 1014 ip 1012 fp 1014 1018 cp 1022 1023 38 1.指针与整数相加减 指针与整数相加、减,表示 指针在内存空间上下移动 移动以其指向对象类型长度为单位 例: int * i p; float * fp ; char *cp ; : cp++
1010 1010 1018 1023 ip 1012 fp 1014 1018 cp 1022 1023 39 1.指针与整数相加减 指针与整数相加、减,表示 指针在内存空间上下移动 移动以其指向对象类型长度为单位 例: int * i p; float * fp ; char *cp ; :
1010 1010 1016 p1 1012 1014 p2 1016 1020 40 2.数组元素指针的比较与相减 例: int * p1, *p2 ; int a [ 5 ] , num ; : p1 = &a[ 0 ] ; p2 = &a[ 3 ] ; num = p2 - p1 ; // 计算元素个数 : if ( p1 == p2 ) // 判断是否指向同一元素 p2++ ; : Example8_5
1 2 3 4 5 1010 1010 1016 p1 1012 1014 p2 1016 1020 输出: num = 3 *p = 4 41 // Example 8_5 # include < iostream . h > main ( ) { int a [ 5 ] = { 1 , 2 , 3 , 4 , 5 } ; int * p1 , * p2 , num ; p1 = & a [ 0 ] ; p2 = & a [ 3 ] ; num = p2 - p1 ; cout << “num=” << num << endl ; if ( p2 = = p1 ) p2 + + ; cout << “* p2 =” << * p2 << endl ; } 想一想 为什么 num 的结果是 3 而不是 6?
42 给指针赋以对应类型的变量地址 int * *p1 , *p2 , k ; : p1 = &p2 ; // 赋给指针类型变量地址 p2 = &k ; // 赋给整型变量地址 3.指针赋值 同类型指针间的赋值 int a , b ; int *pa= &a , *pb = &b; // 以变量地址初始化指针 pa = pb ; // pa与 pb同一指向,都指向变量 b
px x 2 5 y 43 1 * 与 + +、- - 算符运算 + +、- - 级别优于 * ,右结合 例: int x=2 , y ; int * px = &x ; * ( px+1) = 5 ; 3.指针赋值 y = * + + px
px x 2 y 44 * 与 + +、- - 算符运算 + +、- - 级别优于 * ,右结合 例: int x=2 , y ; int * px = &x ; * ( px+1) = 5 ; 3.指针赋值 2 5 5 y = * + + px
px x 2 y 45 * 与 + +、- - 算符运算 + +、- - 级别优于 * ,右结合 例: int x=2 , y ; int * px = &x ; * ( px+1) = 5 ; 3.指针赋值 5 3 y = * + + px 5
px x 2 5 y 46 1 * 与 + +、- - 算符运算 + +、- - 级别优于 * ,右结合 例: int x=2 , y ; int * px = &x ; * ( px+1) = 5 ; 3.指针赋值 y = + + * px
px x 2 y 47 2 * 与 + +、- - 算符运算 + +、- - 级别优于 * ,右结合 例: int x=2 , y ; int * px = &x ; * ( px+1) = 5 ; 3.指针赋值 2 5 y = + + * px
px x 3 y 48 * 与 + +、- - 算符运算 + +、- - 级别优于 * ,右结合 例: int x=2 , y ; int * px = &x ; * ( px+1) = 5 ; 3.指针赋值 5 3 y = + + * px 3 Example8_6
49 3.指针赋值 // Example 8_6 # include < iostream . h > main ( ) { int x = 2 , y ; int * px = & x ; * ( px + 1 ) = 5 ; y = * + + px ; // y = + + * px ; cout << “y=” << y << endl ; }
50 * 与 + +、- - 算符运算 + +、- - 级别优于 * ,右结合 3.指针赋值 (1)p + + 指针指向下一个元素 (2)* p + + 等价于* ( p + + ) 先取 * p 的值,然后使 p 加 1 (3)* + + p 等价于* ( + + p ) 先使 p 加 1,然后取 * p 的值 (4)( * p ) + + * p 的值加 1 - - 算符运算规则相同