1 / 36

C++ 语言基础 —— 补充知识

C++ 语言基础 —— 补充知识. 运行时内存 指针和内存地址 指针地址 指针和数组 动态内存分配 函数调用和内存 结构体 及其 调用 ( 复合数据类型) 输入输出( cout 和 cin )( VC++ 类库的使用). 程序的内存分配. 一个由 c/C++ 编译的程序占用的内存分为以下几个部分 : 1 、栈区( stack ) 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。 其操作方式类似于数据结构中的栈。 2 、堆区( heap )

alina
Télécharger la présentation

C++ 语言基础 —— 补充知识

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. C++语言基础——补充知识 • 运行时内存 • 指针和内存地址 • 指针地址 • 指针和数组 • 动态内存分配 • 函数调用和内存 • 结构体 及其 调用 (复合数据类型) • 输入输出(cout 和 cin)(VC++类库的使用)

  2. 程序的内存分配 一个由c/C++编译的程序占用的内存分为以下几个部分: 1、栈区(stack) 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。 其操作方式类似于数据结构中的栈。 2、堆区(heap) 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表。 3、全局区(静态区)(static) 全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域, 未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。 - 程序结束后有系统释放。 4、文字常量区 常量字符串就是放在这里的。 程序结束后由系统释放。 5、程序代码区 存放函数体的二进制代码。

  3. int a = 0; 全局初始化区char *p1; 全局未初始化区 main() { int b; 栈char s[] = "abc"; 栈char *p2; 栈char *p3 = "123456"; 123456\0在常量区,p3在栈上。 static int c =0; 全局(静态)初始化区 p1 = (char *)malloc(10); p2 = (char *)malloc(20); 分配得来得10和20字节的区域就在堆区。strcpy(p1, "123456"); 123456\0放在常量区,编译器可能会将它与p3所指向的 "123456"优化成一个地方。}

  4. 栈内存的作用 - 函数调用

  5. 堆内存 –动态分配

  6. C++语言基础——补充知识 • 运行时内存 • 指针和内存地址 • 指针地址 • 指针和数组 • 动态内存分配 • 函数调用和内存 • 结构体 及其 调用 • 输入输出(cout 和 cin)

  7. 0000002 65 a 0 0000003 0 0000004 b 0 0000005 1 0000006 0 0000007 0 0000008 c 0 0000009 2 0000010 内存地址 int main(){ char a = ‘A’; int b = 1; float c = 2; double d = 3; return 0; } 值:内存单元中存放的数据 地址:系统分配给变量的内存单元的起始地址

  8. 0000002 0 0000004 65 000000E 0000002 指针变量 存放地址的变量称为指针变量,它用来指向另一个变量,通常用*表示。 int main() { int i=65; int*i_pointer; i_pointer = &i; return 0; }

  9. 定义后 p=&i *p=3 j=*p+2 i 1000 i 1000 3 i 1000 3 i j j j 5 j 1004 1004 1004 p 1000 p 1000 p 1000 p 1008 1008 1008 指针操作 int i, j, *p; p=&i; *p=3; j=*p+2; &:取变量的首地址,即指针; *:取指针所指向的地址中的值; 1000 1004 1008

  10. 课堂练习 • 运行时内存一般分为哪几部分,各有何作用? • 请绘制以下程序内存示意图。 void swap(int a, int b){ int temp; temp = a; a = b; b = temp; } int main(){ int m, n; scanf(“%d %d”, &m, &n); swap(m, n); printf(“%d %d”, m, n); return 0; } 3. 请绘制右边程序段内存示意图。 int i=65; int*i_pointer; i_pointer = &i; char kk = ‘A’; char *pKK = &kk; char jj = *pKK;

  11. 指针ptr-2 指针pt+5 指针ptr+1 1020 992 1004 指针ptr 1000 992 1000 变量i占4字节 ··· ··· 1020 图4.4 指针的算术运算 指针和数组 • 数组元素在存储器中是连续存放的。组名是一个地址常量(指针常量),其值为数组中第一个元素的地址。数组的这些性质以及指针算术运算的特点,使得利用指针可以方便地访问数组元素。

  12. 指针与数组的等价性 // &buf[0] 与pbuf 具有相同的意义。 // 数组名不能运算: ++buf 是错误的。 char buf[ ]; char *pbuf; pbuf-----------------&buf[0] pbuf + 1------------&buf[1] *pbuf---------------buf[0] *(pbuf + 1)--------buf[1] *(pbuf + index)---buf[index]

  13. 例: #include <iostream.h> void main( ) { static int a[5] = {5,4,3,2,4}; int i,j; i = a[2] + a[4]; j = *(a+2) + *(a+4) cout << i << “\n”<< j ; } 输出:7 7

  14. 数组与指针 混用 注意事项 1、数组是数组,指针是指针。 2、数组不能赋值。 3、用数组名可以给指针赋值,得到的值是数组首元素地址。 4、函数传参数时,数组类型的声明实际解释为指针类型的声明。   于是在函数调用时,参数传递就是 2 和 3 的特例:注意传参数就是赋值。

  15. 例: • int a[] = {1,2,3};int *p = a;sizeof a / sizeof(a[0]) == 3;void foo(int p[]); // 同 void foo(int *p);复杂的示例:int a[2][3] = {1,2,3, 4,5,6};// a 是 2 元数组,其元素是 int[3] 即 3 元整数数组void bar(int p[][3]);// 同 void bar(int (*p)[3]); // 参数 p 是指针,其所指元素类型是 int[3] 即 3 元整数数组bar(a); // 调用 bar 时,数组 a 解释为首元素地址,赋给指针参数 p

  16. 使用操作符new和delete进行动态存储分配 • 普通的变量或数组的定义,是在程序被编译时,由编译器为该变量或数组分配存储空间,这样的存储分配称为自动存储分配或静态存储分配(定义对象时使用了关键字static)。这样的存储分配方式有时会给编程带来不便。 • C++提供了动态分配存储空间的方法---即在程序运行过程中,根据实际需要为变量(对象)或数组分配存储空间。这种存储分配方法称为动态存储分配。 • 程序运行时,操作系统为程序分配一块内存空间,存放程序中所有动态创建的变量(对象),这块空间称为程序的自由存储区或堆。

  17. 实现动态存储分配 • C++使用操作符new和delete来完成动态存储分配。 1、动态创建单个变量的语法: 指针名 = new 数据类型; 2、动态创建数组的语法: 指针名 = new 数据类型[表达式1][表达式2]…; • 例如: int *ptr1=new int; //动态创建一个整型变量 float *ptr2=new float[10]; //动态创建包含10个元素的浮点数组, • new操作符用于实现动态存储分配,系统根据数据类型决定所需内存的大小,如果分配成功,则将所分配的内存空间首地址赋值给相同类型的指针变量。 • 可以使用由圆括号扩住的初值表对动态创建的变量进行初始化。例如: float *ptr1=new float(123.45);

  18. 释放动态分配的内存 • 在程序中由操作符new为对象动态分配的存储空间,在程序运行结束前必须用delete操作符动态释放。 • 释放动态创建的变量的语法: delete 指针名; • 释放动态创建的数组的语法: delete [] 指针名;

  19. 例 根据输入的数组长度动态创建整型数组。给 数据元素赋值,并输出数组。 #include<iostream> using namespace std; void main() { int length,i,*ptr1; cout<<"请输入数组的长度: "; cin>>length; ptr1=new int[length]; for(i=0;i<length;i++) *(ptr1+i)=i*10; for(i=0;i<length;i++) cout<<ptr1[i]<<" "; cout<<endl; delete[] ptr1; }

  20. 课堂练习 • 从键盘读入正整数k,并动态创建内存空间,从键盘循环读入k个字符存入该片内存。 void fun() { int k; cin>>k; char *pBuf = new char[k]; for (int i=0; i<k; i++) cin>>pBuf[i]; delete []pBuf; }

  21. C++语言基础——补充知识 • 运行时内存 • 指针和内存地址 • 指针地址 • 指针和数组 • 动态内存分配 • 函数调用和内存 • 结构体 及其 调用 • 输入输出(cout 和 cin)

  22. 函数 的 声明、实现、及 使用 • 函数声明:给函数定一个标准 (一般放在 xx.h 中) 返回值类型 函数名(参数列表…); int Func(int para1, float para2); • 函数实现:具体实现函数声明的功能 (xx.cpp) int Func(int para1, float para2) { …… ; return xxx; } • 函数使用:使用函数 ( main.cpp 或其他调用者) main( ) { int tmp; tmp = Func(100, 200.0); }

  23. main函数 a函数 b函数 ② ③ ④ ① 调用b函数 ⑤ 调用a函数 ⑨ ⑦ ⑥ ⑧ 结束 函数调用中究竟发生了什么? (1)为所有的形参分配内存,计算各个实际参数表达式的值,依次赋予对应的形式参数。(若是“无参函数”,上述工作不执行) (2)进入函数体,执行函数中的语句,实现函数的功能,当执行到“返回语句”时,计算返回值,释放本函数体中的变量等(静态型变量不释放),收回分配给形参的内存,返回主调函数。 (3)继续执行主调函数中的后继语句。

  24. 栈内存的作用 - 函数调用

  25. 参数传递 函数间传递参数有2种方式: 值传递方式(以及指针传递);引用传递方式。 例设计一个数据交换函数swap( ),实现两个数的交换 void swap(int a, int b){ int temp; temp = a; a = b; b = temp; } int main(){ int m, n; scanf(“%d %d”, &m, &n); swap(m, n); printf(“%d %d”, m, n); return 0; } 值传递

  26. 函数参数引用传递 void swap(int &a, int &b){ int temp; temp = a; a = b; b = temp; } int main(){ int m, n; scanf(“%d %d”, &m, &n); swap(m, n); printf(“%d %d”, m, n); return 0; } 引用传递

  27. 函数的重载 int fun(int a, int b) { return a+b; } void main(void) { cout<<fun(3,5)<<endl; cout<<fun(5)<<endl; } int fun (int a) { return a*a; } 所谓函数的重载是指完成不同功能的函数可以具有相同的函数名。 C++的编译器是根据函数的实参来确定应该调用哪一个函数的。

  28. 课堂练习 • 1. 写出求点(x,y)对称点坐标的函数。 • 2. 使用函数重载求2个及3个数中最大值的函数。

  29. C++语言基础——补充知识 • 运行时内存 • 指针和内存地址 • 指针地址 • 指针和数组 • 动态内存分配 • 函数调用和内存 • 结构体 及其 调用 • 输入输出(cout 和 cin)

  30. 结构体的定义 • 结构体 是一种复合 数据类型 • 定义结构体后,结构体名 的使用和一般数据类型类似 structSTUDENT { int num; char name[20]; char sex; int age; float score; char addr[30]; }; STUDENT stu1,stu2; struct 结构体名 { 类型标识符 成员名; 类型标识符 成员名; ……………. }; 结构体名变量列表;

  31. 例 struct student { int num; char name[20]; char sex; int age; float score; char addr[30]; }stu1,stu2; 例 struct student { int num; char name[20]; char sex; int age; float score; char addr[30]; }stu1,stu2; stu1.num=10; 例 struct student { int num; char name[20]; struct date { int month; int day; int year; }birthday; }stu1,stu2; 例 struct student { int num; char name[20]; char sex; int age; float score; char addr[30]; }stu1,stu2; stu1.score=85.5; printf(“%d,%s,%c,%d,%f,%s\n”,stu1); () stu1.birthday.month=12; stu1.score+=stu2.score; stu1.age++; stu1={101,“Wan Lin”,‘M’,19,87.5,“DaLian”}; () stu2=stu1; ( ) 例 struct student { int num; char name[20]; char sex; int age; float score; char addr[30]; }stu1,stu2; birthday num name month day year if(stu1==stu2) …….. () 引用方式: 结构体变量名.成员名 • 结构体变量的引用 • 引用规则 • 结构体变量不能整体引用,只能引用变量成员 • 可以将一个结构体变量赋值给另一个结构体变量 • 结构体嵌套时逐级引用 成员(分量)运算符 优先级: 1 结合性:从左向右

  32. (*结构体指针名).成员名 结构体指针名->成员名 结构体变量名.成员名 p num name struct student { int num; char name[20]; char sex; int age; }stu; struct student *p=&stu; stu sex age main() { struct student { long int num; char name[20]; char sex; float score; }stu_1,*p; p=&stu_1; stu_1.num=89101; strcpy(stu_1.name,"Li Lin"); p->sex='M'; p->score=89.5; printf("\nNo:%ld\nname:%s\nsex:%c\nscore:%f\n", (*p).num,p->name,stu_1.sex,p->score); } • 结构体和指针 • 指向结构体变量的指针 • 定义形式:struct 结构体名 *结构体指针名; 例 struct student *p; • 使用结构体指针变量引用成员形式 存放结构体变量在内存的起始地址 例 int n; int *p=&n; *p=10;  n=10 struct student stu1; struct student *p=&stu1; stu1.num=101;  (*p).num=101 例 指向结构体的指针变量 指向运算符 优先级: 1 结合方向:从左向右

  33. p num name stu[0] sex age p+1 stu[1] stu[2] 例 指向结构体数组的指针 struct student { int num; char name[20]; char sex; int age; }stu[3]={{10101,"Li Lin",'M',18}, {10102,"Zhang Fun",'M',19}, {10104,"Wang Min",'F',20}}; main() { struct student *p; for(p=stu;p<stu+3;p++) printf("%d%s%c%d\n",p->num,p->name,p->sex,p->age); } 指向结构体数组的指针

  34. 目录 • 运行时内存 • 指针和内存地址 • 指针地址 • 指针和数组 • 动态内存分配 • 函数调用和内存 • 输入输出(cout 和 cin)

  35. 标准输出流对象cout • cout是流类库中预定义的对象,它是标准输出流类ostream的对象,代表标准输出设备---显示器。例如: cout<<"Welcome to C++!!!\n"; //向显示器输出字符串 cout<<“i=”<<i<<endl;//向显示器输出变量i的值 • 语句中的“<<”称为插入运算符,功能是把要输出的数据信息插入到输出流中。 • cout是在头文件iostream和iostream.h中定义的,所以要在程序中使用cout,就要使用如下指令包含该头文件。 #include<iostream.h>    或者 #include<iostream> using namespace std;

  36. 标准输入流对象cin • cin也是流类库中预定义的对象,它是标准输入流类istream的对象,代表标准输入设备---键盘。例如: cin>>i>>j; //从键盘输入变量i和j的值 • 语句中的“>>”称为提取运算符,功能是从输入流中提取数据,赋值给程序中的变量。 • cin对象也是在头文件iostream和iostream.h中定义的。

More Related