1 / 38

七、指向数组的指针 八、二级指针 九、指针数组 十、 void 关键字与 void * 型的指针

第 6 章 指针与数组. 七、指向数组的指针 八、二级指针 九、指针数组 十、 void 关键字与 void * 型的指针. 七、指向数组的指针 1. 指向数组的指针的定义和性质 对于第二个维数相同的二维数组如 {int w[3][5],e[6][5];}, w,e 共性地具有类型属性 int(*)[5] ,第一个维数 3,6 协同确定 相应数组的总的内存空间,对于地址的映射计算并不起作 用。通过引进指向列数为 5 的二维数组的指针 x : int (*x)[5]; x 可以分别指向 w,e 。 例如: x=w; x=e+2;

elsie
Download Presentation

七、指向数组的指针 八、二级指针 九、指针数组 十、 void 关键字与 void * 型的指针

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 第6章 指针与数组 • 七、指向数组的指针 • 八、二级指针 • 九、指针数组 • 十、void 关键字与void *型的指针

  2. 七、指向数组的指针 • 1.指向数组的指针的定义和性质 • 对于第二个维数相同的二维数组如{int w[3][5],e[6][5];}, • w,e共性地具有类型属性int(*)[5],第一个维数3,6协同确定 • 相应数组的总的内存空间,对于地址的映射计算并不起作 • 用。通过引进指向列数为5的二维数组的指针x: • int (*x)[5]; • x可以分别指向w,e。 • 例如:x=w; x=e+2; • 指向数组的指针简称为数组指针,一般地指向二维数组 • type d[r][c]的指针定义格式为: • type (*q) [c]; • 类型 (*数组指针名) [整型常数];

  3. 如上定义的指针q为type(*)[c] 类型的指针,是指向列 • 数为c的二维数组的指针。 • 数组指针q是一个指针,因此仅占一个指针对应的存储 • 空间,其中c是静态的整型常数,用于界定数组指针的步长 • 增量m = sizeof (type)*c。 • 一经定义数组指针q,则表达式q[ i ]等价于(*(q+i))为 • type*型右值,这个右值是自动计算出来的,不占数据区内 • 存。 • 表达式q[ i ][ j ]等价于(*(*(q+i)+j))为type型左值,左值 • 的内存应预先由数组定义语句分配。编译器不检查q[ i ][ j ] • 是否初始化,也不管是否越界。

  4. 如果q=d,则可以等价地通过指针名q和二维数组名d来如果q=d,则可以等价地通过指针名q和二维数组名d来 • 索引二维数组。此时关系表达式q[ i ]==d [ i ]为真。 • 在q=d期间q [ i ][ j ]等价于d [ i ][ j ],即对q [ i ][ j ]的操 • 作就是对d [ i ][ j ]的等价操作,如果q是形参,则形参在函 • 数中通过q [ i ][ j ]或**q等方式直接操作相应的实参数组。 • 令n = sizeof (type), m=n*c,q=d的地址为xxxx,则 • q+j的地址值为yyyy= xxxx+j*m。 • type(*)[c]型指针的位移步长增量为m。q+j的地址属性 • 为type(*)[c]。

  5. d [ j ]和q [ j ]构成type*型的右值,其步长增量为n。 • q[ j ]的地址为yyyy,则 q[ j ]+k的地址值为yyyy+kn, • 即指向第j+1行的第k+1个元素,也就是指向 q[ j ][ k ],即关 • 系式q[ j ]+k==&q[ j ][ k ]为真。 • q[ j ]或(*(q+j))与q+j具有相同的地址值但地址类型属性 • 不同。 • 这里访问指针运算(*(q+j))或q[j]表示降维处理即将 • type(*)[c]型的地址降为type*型的右值地址和自动的寻址计 • 算而不表示直接索引内存数据,只有左值才访问操作内存数 • 据。 • d+j表示指向第j+1行,d[ j ]是第j+1行的首地址,两者 • 都指向同一内存位置但地址属性不同。

  6. 二维数组行地址 d [ 0 ] d [ 1 ] d [ 2 ] : d [ j ] : d [ r-1 ] 行地址的值 x x x x x x x x+1m x x x x+2m : x x x x+jm : x x x x+r m-m q+= j-1; q=d+1; 数组指针指向二维数组 每行的首地址,赋值一次 指针用加运算 数组指针向后移动j-1个位置 m=sizeof (type[c])=nc 二维数组type d[r][c]某行的首地址与数组指针的关系

  7. 赋值语句{ q=d; q+= j;}导致q的值为xxxx+jm,此时表 • 达式q[0][k]等价于 d[j][k],**q= q[0][0]=d[j][0]。 • d[0][0]总是索引数组d的第1个元素,q[0][0]未必。q++ • 向前移动一个位移步长即q从当前位置向后移动m个字节, • 也就是值向下一行的内存地址。 • 指针只能用相同属性的地址赋值,当指针不平级时,需 • 要进行指针类型转换。语句: • double d[3][5]; double (*q)[5]=d+1; • double *p=q[0]; • 定义数组指针q,初数化指向二维数组d的第2行,*q和 • d[1]为double *型的右值地址。d, q具有double(*) [5] 类型 • 属性,d=q是错误的,d为右值,q为左值。 • q- = 1; • //向前移动1个double[5]类型的步长,即前移5*8*1=40个字节.

  8. 语句{double(*r)[2];}定义double(*)[2]型的数组指针 • r,r与q类型属性不同,它们之间不能相互赋值。r=d,q=r是 • 错误的,等号两边的类型属性不同。r[ j ][ i ]=d[ i ][ j ]是可 • 以的。r[ i ],q[ j ]都是double型的右值地址,r[ i ]=q[ j ]是错 • 误的,而p = r[ i ],p = q[ j ]是正确的。 • 对于最后两个维数相同的三维数组如: • {int s[2][4][3],h[5][4][3];}, s,h共性地具有类型属性 • int (*)[4][3],第一个维数2,5对于地址的映射不起作用。 • 引进指向三维数组的指针q: • int (*q)[4][3]; • q可以方便地操纵s,h。例如:q=s;q=h+1;

  9. 设m,r,c时静态的整型常数,一般地指向三维数组type • s[ m ][ r ][ c ]的指针定义格式为: • type (*q)[r] [c]; • 类型 (*数组指针名) [常数2][常数3]; • q的类型属性为type (*)[r][c] ,如果q=s,则可以等价地 • 通过指针q和数组名s来索引三维数组。此时关系表达式 • q[ i ][ j ][ k ]==s[ i ][ j ][ k ],q[ i ][ j ]==s[ i ][ j ] • q[ i ]==s[ i ] 为真。 • 下面的关系是等价的,访问指针形式明显缺乏可读性且 • 各级表达式的类型属性含糊,也不容易用键盘输入。因此程 • 序设计中不宜用右边的访问指针形式: • s[ i ][ j ][ k ] == (*(*(*( s+i )+j)+k))

  10. [例]同一个地址对应不同类型的地址属性 • #include <stdio.h> • void main() • { int b[3][2][2]; • //int (*p)[2][2]=b;int (*q)[2]=b[0];int * r=b[0][0]; • printf("%p,%p,%p\t",b,b[0],b[0][0]); • } //输出:0066FDC8, 0066FDC8, 0066FDC8 • 说明: {int b[3][2][2];}中的b具有地址属性int (*)[2][2], • b[0]具有地址属性int (*) [2],b[0][0]具有地址属性int *,它 • 们都具有相同的地址值。b+i,b[i]和b[i][0]也具有相同的值。 • 地址值相同地址类型属性不同的现象表示同一片内存 • 可用不同属性的指针寻址访问。

  11. 2.数组指针形参和二维数组形参 • c是静态的整型常数。下面是两个本质一致外在格式不 • 同的函数原型: • void f (int (*q)[c],...); void f (int q[ ][c],...); • 形如“ int ( *q )[ c ]”的形参为数组指针形参, 形如 • " int q[ ][c]"的形参为二维数组形参。 • 两者都视为int (*)[c]型的指向二维数组的指针,二维数 • 组共性地具有固定列数c。 • 函数定义 void f (int (*q) [ c ],...) {;...;}可等价地改为: • void f (int q[ ][ c ],...){;...;} 。

  12. [例]指向二维数组的指针与二维数组 • # include<iostream.h> • void f (float (*q)[4],int m) • { for (int k=0;k<m;k++) • { float* p=q[ k ]; • for( int j=0;j<4;j++) • cout<< p[ j ]<<"," ; • } • } • void main (void) • { float d[ ][4]={0,1,2,3,4,5,6,7}; • int const M=sizeof (d)/sizeof (*d); • f (d,M); • f (d+1,M-1); • } //输出:0,1,2,3,4,5,6,7, 4,5,6,7,

  13. [例]数组指针形参或二维数组形参实现求数组空间[例]数组指针形参或二维数组形参实现求数组空间 • 的和 • #include<stdio.h> • double sum (double q[ ][3],int n); • void main (void) • { double b[2][3]={1,2,3,4,5,6}; • printf ("%2.0f,%2.0f\n",sum (b,2),sum (b+1,1)); • double a[ ]={1,2,3,4,5,6,7}; • typedef double (*QA)[3]; • printf("%2.0f,%2.0f\n",sum((QA)a,2),sum((QA)(a+4),1)); • }

  14. double sum (double (*q)[3],int n) • { double s=0 ; int i,j; double *p; • for ( i=0; i<n; i++, q++) • for (j=0, p=*q; j< 3; j++, p++) • s+=*p; • return s; • } • double sum1(double (*q)[3],int n) • { double s=0 ; • for (int i=0;i<n;i++) for (int j=0; j<3;j++) s+=q[ i ][ j ]; • return s; • }

  15. typedef简化数组定义 • 数组指针的定义语句[int (*p)[N];]定义了一个指针变量 • p,定义语句[int d[M][N];]定义了一个二维数组d,可以通过 • typedef类型声明语句来建立一个数组类的别名,其格式 • 为: • typedef int (*PN)[N]; • // PN是int (*)[N]类型的别名 • typedef int AMN[M][N]; • // AMN是int[M][N]类型的别名 • typedef int AN[N]; • // AN是int[N]类型的别名,N,M是静定的整数。

  16. 去掉上面的typedef就得到数组定义语句。可用类型别去掉上面的typedef就得到数组定义语句。可用类型别 • 名定义数组或指针。 • PN p,q,r; • //定义指针变量p,q,r都拥有数据类型int (*)[N] • AN a,b; • //定义数组a,b其类型属性为int[N],等价于int a[N], b[N]; • AMN c,d; • //相当于定义二维数组int c[M][N], d[M][N];

  17. # include <iostream.h> • const int L=2,M=2,N=2; • typedef int ALMN[ L][ M ][ N ]; • typedef int (*PMN)[M][N]; typedef int (*PN)[N]; • void main (void) • { int j, k; • ALMN v= {1, 2,3, 4,5,6,7,8}; • PMN d=v; PN a= v[1]; • for (j=0;j<M;j++) for (k=0;k<N; k++) • cout<<d[1][j][k]<<"," ; • for (j=0;j<M;j++) for(k = 0; k <N; k++) • cout<<a[j][k]<<";" ; • } ///输出结果: 5 ,6 ,7 ,8, 5 ;6 ;7 ;8;

  18. 八、二级指针 • 二级指针的定义格式为: • type** pp1 , **pp2 ,…,**ppn; • 类型** 指针名1,**指针名2,…,**指针名n; • 二级指针初始化定义语句的格式为: • type** pp = ptrExpression; • 类型** 指针名=指针表达式; • 指针表达式是与所定义的指针同类型的地址值。如上定 • 义的指针pp,pp1, pp2, ppn等抽象地称为type**类型的指针 • 或二级指针。二级指针的地址对应一个三级指针,基本上不 • 使用三级指针。一级指针的地址是右值,二级指针是一种存 • 放一级指针的地址数据的特殊类型变量,简单地说二级指针 • 是一级指针的地址的变量。

  19. 二级指针具有下面的特性: • 1.二级指针的类型属性,二级指针的类型是其所指向地 • 址变量的类型,二级指针的类型属性限定二级指针的增减以 • 指针类型步长sizeof(type*)=4或2为单位。二级指针可在一 • 级指针构成的数组空间中移动。pp++表示向后移动4或2个 • 字节。 • 2.一经定义二级指针pp,则表达式pp[ I ]等价于(*(pp+i)) • 为type*型左值;表达式pp[ I ][ j ]等价于(*(*(pp+i)+j))为 • type型左值,编译器不负责它们的内存分配,不检查它们是 • 否初始化,也不管是否越界。

  20. &c &p 2.0 p pp c • pp[ j ]或(*(pp+j))与pp+j的地址值不同地址属性也不同. • 这里访问指针运算(*(pp+j))或pp[ j ]既表示降维处理也表示 • 直接索引pp+j指向的内存数据。pp+j的地址值自动根据关系 • 式(char*)pp+j*sizeof (type*)计算,而pp[ j ]的值由用户确定. • 当一级指针指向单一的变量或二级指针指向单一的一级 • 指针时,对于指针的加减运算都是越界行为,应予以避免。 double c,b; • double *p,**pp; • p=&b; pp= &p; *p=5.0; p=&c; • **pp=2.0; //等价于**pp*(*(&p))*(p)*(&c)c,c=2.0

  21. 九、指针数组 • 1.指针数组的定义和性质 • type*型的指针数组的定义格式为: • type *pa[N]; 类型 * 指针数组名[数组长度]; • 指针数组具有一维数组的一般性质,占有N个指针所需 • 的内存空间,而其特点如下: • a. pa为指针数组名,本身代表指针数组的首地址,此地 • 址是type**型的右值地址。 • sizeof (pa)=sizeof (type*[N])= N *sizeof (type*)。 • N= sizeof(pa)/ sizeof(pa[0])

  22. b.指针数组的每一个元素pa[i]是type*型的左值,pa [i] • 等价于(*(pa+i));表达式pa[ I ][ j ]等价于(*(*(pa+i)+j))为 • type型左值,pa[ I ]的作用相当于一级指针p的作用,pa+I • 指向元素pa[ I ],pa[ I ]+j或*(pa+i)+j 指向变量pa[i][j].指针 • 数组的元素的初始化可由赋值语句进行,也可根据下面的格 • 式进行: • type *pa[ N ] ={initialList}; • 类型 *指针数组名[ ]={初始化地址列表}; • 初始化地址列表的每一个表达式应是type*型的地址。 • 对于type x,a[N],d[r][c];,如果指针数组元素pa[ i ]=a,则 • pa[ i ][ j ]索引一维数组元素a[ j ]。如果指针数组元素 • pa[ I ]=d[ k ],则pa[ I ][ j ]索引二维数组元素d[ k ][ j ]。如 • 果指针数组元素pa[ k ]=&x,则*pa[ k ]索引变量x。

  23. 例如: • double d[ 3 ][ 2 ]={1,2,{3,4},5,6}; • double* y[3]={d[2],d[1],d[0]}; • 相当于: y[0] =d[2]; y[1] = d[1]; y[2] = d[0]; • 此时有:y[0][0]=d[2][0]=5 ; y[1][0]=d[1][0]=3 ; • y[2][0]=d[0][0]=1 ; y[0][1]=d[2][1]=6 ; • y[1][1]=d[1][1]=4 ; y[2][1]=d[0][1]=2 ; • 指针数组的相邻元素指向的数据不必具有相邻的关系; • 指针数组的元素可指向生存期稳定的全局变量、静态变量也 • 可指向生存期瞬态变化的局部变量,尚可指向生存期由程序 • 员控制的堆空间。 • 但应保证指针指向的数据生存期对于指针具有可操作 • 性,或者说指针操作的内存数据的生存期在指针访问时是有 • 效的,是存在的。

  24. 指针数组元素 pa[ 0 ] pa[ 1 ] pa[ 2 ] : pa[ j ] : pa[N -1] 指针的初值 t1 t2 t3 : t5 : t7 t1的元素 t1[ 0 ] t[ 1 ] t1[ 2 ] : t1[ 4 ] : t1[ 6 ] pp=pa; pp+=j; • 考虑:typedef char type ; • type t1[7],t2[6],t3[5],t4[4],t5[3],t6[2], t7[1]; • type *pa[ ]={t1,t2,t3,t4,t5,t6,t7}; • type **pp=pa; 图 指针数组的值与二级指针

  25. [例]指针数组的元素指向维数大小不同的一维数组[例]指针数组的元素指向维数大小不同的一维数组 • # include<stdio.h> • void show (long * a,int n) • { for (int k=0;k<n;k++) printf ("%d ",a[ k ]); • printf("-"); • } • long t1 [ 7 ]={1,2,3,4,5,6,7}; • void main() • { long t4[ 4 ]={1,2,3,4}; long *pa[ 3 ]={t4,t1}; • long ** pp=pa+1; • show (pa[0],4); show (pp[0-1],4); • show (pa[1],7); show (pp[1-1],7); • }//输出结果: 1 2 3 4 -1 2 3 4 -1 2 3 4 5 6 7 -1 2 3 4 5 6 7 -

  26. 2.二级指针形参和指针数组形参: • 如下是两个本质一致外在格式不同的函数原型: • int f (int **pp,...); int f (int *pp[],...); • 形如"int**pp"的形参为二级指针形参, 形如"int*pp[]“ • 的形参为指针数组形参,两者都视为 int**型的表达式。指 • 针数组形参要求实参指针数组的内存分配,每一元素的初始 • 化和相应元素指向的数据的内存分配。二级指针形参表明定 • 位内存地址的基准特性。 • 函数定义int f (int *pp[ ],...){;...;}等价于函数定义 • int f (int **pp,...) {;函数体代码不变;} • 引入一级指针用于访问变量或数组元素,引入指针数组 • 用于通过访问指针元素,最终访问指针元素指向的变量。

  27. 二级指针pp=pa,pp[ k ]等价于pa[ k ],对pp[ k ]的操作 • 就是对一级指针pa[k] 操作;如果pp是形参,则形参在函数中 • 通过pp [ i ]或*pp等方式直接操作相应的实参指针数组空间, • 通过pp[ i ][ j ]或**pp等方式操作相应的实参变量数组空间 . • [例]二级指针显示指针数组的元素指向的变量的值 • #include <stdio.h> • void f (int**pp,int n) • { for (int i=0;i<n;i++) printf ("%d,",**pp++); } • void main() • { int x=1,y[ ]={2,3},u[ ][1]={4,5}; • int * px [ ]={&x, &y[0], y+1, u[0], &u[1][0]}; • f (px,5); f (px+4,5-4); • for (int** pp=px, i=0; i<5; i++, pp++) • printf ("%d, ", **pp); }

  28. [例]二级指针或指针数组作为形参实现求数组的和[例]二级指针或指针数组作为形参实现求数组的和 • #include<stdio.h> • double sum (double** pp, int n, int m=3); • double a[ ] = {2,3,4}; • void main (void) • { double b[2][3] = {1,2,3,4,5,0}; • double* x[ ]= {b[1],b[0],a}; • const char*fmt = "%2.0f,%2.0f,%2.0f "; • printf (fmt, sum (x,2), sum (x+1,1),sum (x+2,1)); • }

  29. double sum (double* pp[ ], int n, int m) • { double s=0 ; int i, j; double *p; • for ( i=0; i<n; i++, pp++) • for (j=0, p=*pp; j<m; j++, p++) • s+=*p; return s; } • double sum1 (double* pp[ ], int n, int m) • { double s=0 ; • for (int i=0; i<n; i++) for (int j=0; j<m; j++) s+=pp [ i ][ j ]; • return s; }

  30. 对指针表达式或下标表达式降维过程中,二级指针和指对指针表达式或下标表达式降维过程中,二级指针和指 • 向二维数组的指针降维的结果恰好殊途同归: • double **型指针pp的下标表达式pp [ j ]+k是double * • 的地址,pp [ j ][ k ]是double的变量; • double(*)[3]型的数组指针q构成的下标表达式q[ j ]+k • 也是double *的地址,q[ j ][ k ]也是double的变量。 • 数组指针指向的内存具有连续递增的特点,q[ j ]是右 • 值;q[ j ]和q[ j+1 ]具有相近的性质,或者均指向全局数据 • 区,或者都指向局部内存区。

  31. 而指针pp[ j ]可作为左值,pp[ j ]和pp[ j+1]未必具有相 • 临的性质;pp[ j ]指向局部空间的时候,pp[j+1]可以指向全 • 局数组。 • q[ j ]是自动计算出来的值,其等于q+j的值;而pp[ j ]最 • 终通过赋值得到。 • 形如double d [ N ][ M ]的二维数组,如果需要匹配 • double * pp [ N ]的指针数组形参,调用之前可通过步骤进 • 行初始赋值: • for (int k=0; k<N; k++) pp[ k ] = d[ k ];

  32. 对于[double a[ M ]; double * p=a; ]容易看出表达式 • p[ n ]和p[0]+n是double型的变量,p [ n ]表示数组的元素 • a [n],p[0]+n表示a[0]加上n。 • 类似地,表达式pp[n]或*(pp+n)与表达式 pp[0]+n或 • *pp+n 是double*型的地址,但具有不同的含义: • *(pp+n)或pp[ n ]表示指针数组中的第n+1个元素为左 • 值,*pp+n 或pp[ 0 ]+n表示在指针数组当前元素(第一个元 • 素) 位置上后移n个类型步长,pp[ 0 ]+n为右值指向 • pp[ 0 ][ n ]。

  33. 十、void 关键字与void *型的指针 • void关键字只有三种用法: • 1.声明一个无返回值的函数,例如: • [void function(int j);],void 型函数调用一般只单独调用; • 2.声明一个不需要任何入口参数的函数,例如: • [int funct (void);]说明funct是一个不需要任何入口参数的 • 函数,其返回值为整型,funct()可作为整型右值参入各种运算; • 3.定义一个void*型的指针(用type表示区别于void的特 • 定类型,如算术类型等); • void*型的指针是一种宽泛类型的指针,void*型的指针 • 需要显式地转换为其它特定类型的指针,其它特定类型的指 • 针可隐含地转换为void*型的指针。

  34. 例如: • void* pv; type* pt, a, b; pt=(type*)pv; pv=pt; • void*型的指针本身绝不直接用于访问数据,即 • *pv= (void)a 以及b= (type)(*pv)形式的表达式是无意义 • 的。 • void*型的指针涉及到的内在含义 : •  void*型的指针与void类型的函数,共借用同样一个 • 关键字,但其内在含义实质上无任何联系。特定类型的指针 • 可以隐含地支付给void*型的指针,这里所谓的隐含实际上 • 是编译器默许的指针转换,本质上带有强制性质。在采用 • void*型指针的值访问内存空间前必须显式地转换或回归到 • 确定类型的指针。

  35. void*型的指针存放内存空间的宽泛的地址。将其它void*型的指针存放内存空间的宽泛的地址。将其它 • 类型的地址统一地存放在void*型指针中是旨在减少显式类 • 型转换引起的代码书写量。 • void*型的指针作为一种内存的定位基准,通用于操 • 作内存的数据。type*型指针的步长增量为sizeof (type)。 • 但void*型指针的类型步长增量是漂移的,没有void类 • 型的数据,sizeof(void)是不允许的,因此不对void*型指针 • 进行指针加减和访问运算,如pv++,*pv等是不允许的。这 • 种类型的宽泛性表明其数据操作的不完备性。 • 因此用void*型的指针编写入口形参时务必补充另一个 • 不可或缺的信息,即界定内存空间的精确大小。

  36. 供应商提供的void*型函数如memset ,memcpy等必然 • 要伴随一个size_t类型的参数来完备内存数据的操作, size_t • 是由类型声明语句[typedef unsigned int size_t;]引入的别 • 名,在函数内部另外具有确定类型的指针来进行具体的数据 • 运算,这种确定的指针类型一般隐含地是C语言中的char*。 • 系统的memset通常直接用汇编语言实现。memset函 • 数原型为: • void * memset (void *buf, int c, size_t n); • // 返回void* 类型指针的函数 • 函数原型中c指出填充内存缓冲区的值,n为填充的元 • 素数目,buf指向缓冲区的地址。函数返回指向buf的指针。

  37. [例] void*指针的编程特点.(函数版本模拟系统的 • memset作用 ) • void* memset (void* pv, int c,size_t n) • { char * pt= (char *)pv ; • for(unsigned int k=0;k<n;k++) *pt++= (char)c; • return pv; • } • #include <iostream.h> • void main() • { char str[ ] = "123456789abcd"; • cout << str << " "; • char* result = (char*) memset (str, '8', 9); • cout << result << endl; • } //输出结果:123456789abcd 888888888abcd

  38. 请打开“第6章(4).ppt”

More Related