C++内存管理 :http://www.cnblogs.com/lancidie/archive/2011/08/05/2128318.html
c/c++内存机制
一:C语言中的内存机制在C语言中,内存主要分为如下5个存储区:
(1)栈(Stack):位于函数内的局部变量(包括函数实参),由编译器负责分配释放,函数结束,栈变量失效。
(2)堆(Heap):由程序员用malloc/calloc/realloc分配,free释放。如果程序员忘记free了,则会造成内存泄露,程序结束时该片内存会由OS回收。
(3)全局区/静态区(Global Static Area): 全局变量和静态变量存放区,程序一经编译好,该区域便存在。并且在C语言中初始化的全局变量和静态变量和未初始化的放在相邻的两个区域(在C++中,由于全局变量和静态变量编译器会给这些变量自动初始化赋值,所以没有区分了)。由于全局变量一直占据内存空间且不易维护,推荐少用。程序结束时释放。
(4)C风格字符串常量存储区: 专门存放字符串常量的地方,程序结束时释放。
(5)程序代码区:存放程序二进制代码的区域。
二:C++中的内存机制
在C++语言中,与C类似,不过也有所不同,内存主要分为如下5个存储区:
(1)栈(Stack):位于函数内的局部变量(包括函数实参),由编译器负责分配释放,函数结束,栈变量失效。
(2)堆(Heap):这里与C不同的是,该堆是由new申请的内存,由delete或delete[]负责释放
(3)自由存储区(Free Storage):由程序员用malloc/calloc/realloc分配,free释放。如果程序员忘记free了,则会造成内存泄露,程序结束时该片内存会由OS回收。
(4)全局区/静态区(Global Static Area): 全局变量和静态变量存放区,程序一经编译好,该区域便存在。在C++中,由于全局变量和静态变量编译器会给这些变量自动初始化赋值,所以没有区分了初始化变量和未初始化变量了。由于全局变量一直占据内存空间且不易维护,推荐少用。程序结束时释放。
(5)常量存储区: 这是一块比较特殊的存储区,专门存储不能修改的常量(如果采用非正常手段更改当然也是可以的了)。
三:堆和栈的区别
3.1 栈(Stack)
具体的讲,现代计算机(冯诺依曼串行执行机制),都直接在代码低层支持栈的数据结构。这体现在有专门的寄存器指向栈所在的地址(SS,堆栈段寄存器,存放堆栈段地址);有专门的机器指令完成数据入栈出栈的操作(汇编中有PUSH和POP指令)。
这种机制的特点是效率高,但支持数据的数据有限,一般是整数、指针、浮点数等系统直接支持的数据类型,并不直接支持其他的数据结构(可以自定义栈结构支持多种数据类型)。因为栈的这种特点,对栈的使用在程序中是非常频繁的 。对子程序的调用就是直接利用栈完成的。机器的call指令里隐含了把返回地址入栈,然后跳转至子程序地址的操作,而子程序的ret指令则隐含从堆栈中弹出返回地址并跳转之的操作。
C/C++中的函数自动变量就是直接使用栈的例子,这也就是为什么当函数返回时,该函数的自动变量自动失效的原因,因而要避免返回栈内存和栈引用,以免内存泄露。
3.2 堆(Heap)
和栈不同的是,堆得数据结构并不是由系统(无论是机器硬件系统还是操作系统)支持的,而是由函数库提供的。基本的malloc/calloc/realloc/free函数维护了一套内部的堆数据结构(在C++中则增加了new/delete维护)。
当程序用这些函数去获得新的内存空间时,这套函数首先试图从内部堆中寻找可用的内存空间(常见内存分配算法有:首次适应算法、循环首次适应算法、最佳适应算法和最差适应算法等。os的基本内容!!)。如果没有可用的内存空间,则试图利用系统调用来动态增加程序数据段的内存大小,新分配得到的空间首先被组织进内部堆中去,然后再以适当的形式返回给调用者。当程序释放分配的内存空间时,这片内存空间被返回到内部堆结构中,可能会被适当的处理(比如空闲空间合并成更大的空闲空间),以更适合下一次内存分配申请。 这套复杂的分配机制实际上相当于一个内存分配的缓冲池(Cache),使用这套机制有如下几个原因:
(1)系统调用可能不支持任意大小的内存分配。有些系统的系统调用只支持固定大小及其倍数的内存请求(按页分配);这样的话对于大量的小内存分配来说会造成浪费。
(2)系统调用申请内存可能是代价昂贵的。 系统调用可能涉及到用户态和核心态的转换。
(3)没有管理的内存分配在大量复杂内存的分配释放操作下很容易造成内存碎片。
3.3 栈和堆的对比
从以上介绍中,它们有如下区别:
(1)栈是系统提供的功能,特点是快速高效,缺点是由限制,数据不灵活;
堆是函数库提供的功能,特点是灵活方便,数据适应面广,但是效率有一定降低。
(2)栈是系统数据结构,对于进程/线程是唯一的;
堆是函数库内部数据结构,不一定唯一,不同堆分配的内存无法互相操作。
(3)栈空间分静态分配和动态分配,一般由编译器完成静态分配,自动释放,栈的动态分配是不被鼓励的;
堆得分配总是动态的,虽然程序结束时所有的数据空间都会被释放回系统,但是精确的申请内存/释放内存匹配是良好程序的基本要素。
(4)碎片问题
对于堆来讲,频繁的new/delete等操作势必会造成内存空间的不连续,从而造成大量的碎片,使程序的效率降低;对于栈来讲,则不会存在这个问题,因为栈是后进先出(LIFO)的队列。
(5)生长方向
堆的生长方向是向上的,也就是向这内存地址增加的方向;对于栈来讲,生长方向却是向下的,是向着内存地址减少的方向增长。
(6)分配方式
堆都是动态分配的,没有静态分配的堆;
栈有两种分配方式:静态分配和动态分配。静态分配是编译器完成的,比如局部变量的分配。动态分配则由alloca函数进行分配,但是栈的动态分配和堆不同,它的动态分配是由编译器进行释放,无需我们手工实现。
(7)分配效率
栈是机器系统提供的数据结构,计算机在底层提供支持,分配有专门的堆栈段寄存器,入栈出栈有专门的机器指令,这些都决定了栈的高效率执行。
堆是由C/C++函数库提供的,机制比较复杂,有不同的分配算法,易产生内存碎片,需要对内存进行各种管理,效率比栈要低很多。
四:具体实例分析
例子(一)
看下面的一小段C程序,仔细体会各种内存分配机制。
int a = 0; //全局初始化区,a的值为0
char *p1; //全局未初始化区(C++中则初始化为NULL)
int main()
{
int b; //b分配在栈上,整型
char s[] = "abc"; //s分配在栈上,char *类型;"abc\0"分配在栈上,运行时赋值,函数结束销毁
char *p2; //p2分配在栈上,未初始化
char *p3 = "123456"; //p3指向"123456"分配在字符串常量存储区的地址,编译时确定
static int c = 0; //c在全局(静态)初始化区,可以多次跨函数调用而保持原值
p1 = (char *)malloc(10); //p1在全局未初始化区,指向分配得来得10字节的堆区地址
p2 = (char *)malloc(20); //p2指向分配得来得20字节的堆区地址
strcpy(p1, "123456"); //"123456"放在字符串常量存储区,编译器可能会将它与p3所指向的"123456"优化成一块
return 0;
}
例子(二)
看下面的一小段代码,体会堆与栈的区别:
int foo()
{
//其余代码
int *p = new int[5];
//其余代码
return 0;
}
其中的语句int *p = new int[5];就包含了堆与栈。其中new关键字分配了一块堆内存,而指针p本身所占得内存为栈内存(一般4个字节表示地址)。这句话的意思是在栈内存中存放了一个指向一块堆内存的指针p。在程序中先确定在堆中分配内存的大小,然后调用new关键字分配内存,最后返回这块内存首址,放入栈中。汇编代码为:
int foo()
{
008C1520 push ebp
008C1521 mov ebp,esp
008C1523 sub esp,0D8h
008C1529 push ebx
008C152A push esi
008C152B push edi
008C152C lea edi,[ebp-0D8h]
008C1532 mov ecx,36h
008C1537 mov eax,0CCCCCCCCh
008C153C rep stos dword ptr es:[edi]
int *p = new int[5];
008C153E push 14h
008C1540 call operator new[] (8C1258h)
008C1545 add esp,4
008C1548 mov dword ptr [ebp-0D4h],eax
008C154E mov eax,dword ptr [ebp-0D4h]
008C1554 mov dword ptr [p],eax
return 0;
008C1557 xor eax,eax
}
008C1559 pop edi
008C155A pop esi
008C155B pop ebx
008C155C add esp,0D8h
008C1562 cmp ebp,esp
008C1564 call @ILT+395(__RTC_CheckEsp) (8C1190h)
008C1569 mov esp,ebp
008C156B pop ebp
008C156C ret
如果需要释放内存,这里我们需要使用delete[] p,告诉编译器,我要删除的是一个数组。
例子(三)
看下面的一小段代码,试着找出其中的错误:
#include <iostream>
using namespace std;
int main()
{
char a[] = "Hello"; // 分配在栈上
a[0] = 'X';
cout << a << endl;
char *p = "World"; // 分配在字符串常量存储区的地址
p[0] = 'X';
cout << p << endl;
return 0;
}
发现问题了吗?是的,字符数组a的容量是6个字符,其内容为"hello\0"。a的内容时可以改变的,比如a[0]='X',因为其是在栈上分配的,也就是在运行时确定的内容。但是指针p指向的字符串"world"分配在字符串常量存储区,内容为"world\0",常量字符串的内容时不可以修改的。从语法上来说,编译器并不觉得语句p[0]='X'有什么问题,但是在运行时则会出现"access violation"非法内存访问的问题。
以下几个函数的变化要看清楚了:吐舌笑脸
char *GetString1(void)
{
char p[] = "hello,world"; //结果:h。由于数组指针指向第一元素的地址,所以调用之后是h
return p;
}
char *GetString2(void)
{
char *p = "hello,world"; //结果:hello,world。由于p指向“hello,world”字符串常量区域地址
return p;
}
char *GetString3(void)
{
char *p = (char *)malloc(20); // 指向p所分配的堆上的内存空间。
return p;
}
char *GetString4(void)
{
char *p = new char[20]; // 指向p所分配的内存空间,p本身在栈上的,p所指向的空间是堆上的。
return p;
}
附录:内存管理注意事项
【规则1】用malloc或new申请内存之后,应该立即检查指针值是否为NULL,防止使用指针值为NULL的内存,可以在函数入口处断言检测。
【规则2】不要忘记为数组或动态内存赋初值(比如calloc比malloc就要好),指针初始化为NULL(c++中为0)。
【规则3】避免数组或指针下标越界,特别太阳当心发生“多1”或者"少1"太阳的操作。
【规则4】动态内存的申请和释放必须配对,防止内存泄露,具体为malloc/calloc/realloc和free配对,new和delete以及delete[]配对。
【规则5】用free或者delete释放内存后,应立即将指针设置为NULL(C++中为0),防止产生“野指针”、"悬垂指针"。
【规则6】遇到不懂得问题及时debug,一般的虫子灯泡debug一下就灰飞烟灭了,一切bug都是浮云而已。
#include <iostream>
using namespace std; //包含iostream.h头文件
main()
{
//输入输出字符
char c;
cin>>c;
cout<<"c="<<c<<endl;
//输入输出整型数据
int n;
cin>>n;
cout<<"n="<<n<<endl;
//输入输出浮点型数据
double x;
cin>>x;
cout<<"x="<<x<<endl;
//输入提示
cout<<"n=";
cin>>n;
cout<<"n="<<n<<endl;
//多项输入
cout<<"c n x"<<endl;
cin>>c>>n>>x;
cout<<"c="<<c<<" n="<<n<<" x="<<x<<endl;
}
#include <iostream>
using namespace std; //包含iostream.h头文件
main()
{
//声明整型变量
int a,b;
//从键盘上为整型变量赋值
cout<<"a=";
cin>>a;
cout<<"b=";
cin>>b;
//整型数的算术运算
cout<<a<<"+"<<b<<"="<<a+b<<endl;
cout<<a<<"-"<<b<<"="<<a-b<<endl;
cout<<a<<"*"<<b<<"="<<a*b<<endl;
cout<<a<<"/"<<b<<"="<<a/b<<endl;
cout<<a<<"%"<<b<<"="<<a%b<<endl;
//测试溢出
short n=32767,m; //n取short类型的最大值
cout<<"n="<<n<<endl;
m=n+1; //引起溢出
cout<<"n+1="<<m<<endl;
}
#include <iostream>
using namespace std; //包含iostream.h头文件
main()
{
//声明变量,并初始化
int a=010,b=10,c=0X10;
//以十进制形式显示数据
cout<<"DEC:";
cout<<" a="<<a;
cout<<" b="<<b;
cout<<" c="<<c<<endl;
//以八进制形式显示数据
cout<<"OCT:";
cout<<oct; //指定八进制输出
cout<<" a="<<a;
cout<<" b="<<b;
cout<<" c="<<c<<endl;
//以十六进制形式显示数据
cout<<"HEX:";
cout<<hex; //指定十六进制输出
cout<<" a="<<a;
cout<<" b="<<b;
cout<<" c="<<c<<endl;
//八、十和十六进制数混合运算并输出
cout<<"a+b+c=";
cout<<dec; //恢复十进制输出
cout<<a+b+c<<endl;
//测试八、十和十六进制输入
cout<<"DEC:a="; cin>>a;
cout<<"OCT:b="; cin>>b;
cout<<"HEX:a="; cin>>c;
cout<<"DEC:"<<dec<<endl; //指定十进制输出
cout<<"a="<<a<<endl;
cout<<"b="<<b<<endl;
cout<<"c="<<c<<endl;
}
#include <iostream> using namespace std; //包含iostream.h头文件
#include<iomanip.h> // iomanip.h头文件包含setprecision()的定义
main()
{
//float型变量的声明、输入、计算和输出
float fx,fy;
cout<<"fx=";
cin>>fx;
cout<<"fy=";
cin>>fy;
cout<<fx<<"+"<<fy<<"="<<fx+fy<<endl;
cout<<fx<<"-"<<fy<<"="<<fx-fy<<endl;
cout<<fx<<"*"<<fy<<"="<<fx*fy<<endl;
cout<<fx<<"/"<<fy<<"="<<fx/fy<<endl<<endl;
//cout<<fx<<"%"<<fy<<"="<<fx%fy<<endl; Error!
//double型变量的声明、输入、计算和输出
float dx,dy;
cout<<"dx=";
cin>>dx;
cout<<"dy=";
cin>>dy;
cout<<dx<<"+"<<dy<<"="<<dx+dy<<endl;
cout<<dx<<"-"<<dy<<"="<<dx-dy<<endl;
cout<<dx<<"*"<<dy<<"="<<dx*dy<<endl;
cout<<dx<<"/"<<dy<<"="<<dx/dy<<endl<<endl;
//cout<<fx<<"%"<<fy<<"="<<fx%fy<<endl; Error!
//测试float和double类型数据的有效位
fx=10.0;fy=6.0;
float fz=fx/fy;
dx=10.0;dy=6.0;
double dz=dx/dy;
cout<<"fz=";
cout<<setprecision(20)<<fx<<"/"<<fy<<"="<<fz<<endl;
cout<<"dz=";
cout<<setprecision(20)<<dx<<"/"<<dy<<"="<<dz<<endl<<endl;;
//float型溢出
float x=3.5e14;
cout<<"x="<<x<<endl;
cout<<"x*x="<<x*x<<endl;
cout<<"x*x*x="<<x*x*x<<endl;
}
#include <iostream>
using namespace std; //包含iostream.h头文件
main()
{
//字符类型变量的声明
char c1='A';
char c2;
//字符数据的运算及输出
c2=c1+32;
cout<<"c1="<<c1<<endl;
cout<<"c2="<<c2<<endl;
//输出字符及ASCII码
cout<<c1<<" : "<<int(c1)<<endl;
cout<<c2<<" : "<<int(c2)<<endl;
cout<<'$'<<" : "<<int('$')<<endl;
//输入字符
cout<<"c1 c2"<<endl;
cin>>c1>>c2;
cout<<"c1="<<c1<<" c2="<<c2<<endl;
}
#include <iostream> using namespace std; //包含iostream.h头文件
main()
{
char c1='\a',TAB='\t';
//阵铃一声
cout<<c1<<endl;
//使用水平制表符
cout<<1<<TAB<<2<<TAB<<3<<TAB<<4<<endl;
//使用双引号
cout<<"He said \"Thank you\"."<<endl;
//使用回车换行
cout<<"abc\n"<<"def"<<'\n';
}
#include <iostream> using namespace std; //包含iostream.h头文件
main()
{
//声明bool变量,并初始化
bool flag1=false,flag2=true;
//输出布尔常量和变量
cout<<"false:"<<false<<endl;
cout<<"true: "<<true<<endl;
cout<<"flag1="<<flag1<<endl;
cout<<"flag2="<<flag2<<endl;
//布尔变量的赋值和输出
int x=1;
flag1=x>0; //存放关系运算结果
cout<<"flag1="<<flag1<<endl;
flag2=flag1; //bool类型变量相互赋值
cout<<"flag2="<<flag2<<endl;
//布尔变量超界处理
flag1=100;
cout<<"flag1="<<flag1<<endl;
flag2=-100;
cout<<"flag2="<<flag2<<endl;
}
#include <iostream> using namespace std;
const double PI=3.1416; //声明常量(const变量)PI为3.1416
main()
{
//声明3个变量
double r,l,s;
//输入圆的半径
cout<<"r=";
cin>>r;
//计算圆的周长
l=2*PI*r;
cout<<"l="<<l<<endl;
//计算圆的面积
s=PI*r*r;
cout<<"s="<<s<<endl;
}
#include<iostream.h>
main()
{
//定义枚举类型,并指定其枚举元素的值
enum color {
RED=3,
YELLOW=6,
BLUE=9
};
//声明枚举变量a和b,并为枚举变量a赋初值
enum color a=RED;
color b; //合法,与C语言不同
// 输出枚举常量
cout<<"RED="<<RED<<endl;
cout<<"YELLOW="<<YELLOW<<endl;
cout<<"BLUE="<<BLUE<<endl;
//枚举变量的赋值和输出
b=a;
a=BLUE;
cout<<"a="<<a<<endl;
cout<<"b="<<b<<endl;
//a=100; 错误!
//a=6 也错误!
//枚举变量的关系运算
b=BLUE; // 枚举变量的赋值运算
cout<<"a<b="<<(a<b)<<endl;
}
#include <iostream> using namespace std;
const double PI=3.1416; //声明常量(const变量)PI为3.1416
main()
{
//声明3个变量
double r=3,l,s;
//计算圆的周长
l=2*PI*r;
cout<<"l="<<l<<endl;
//计算圆的面积
s=PI*r*r;
cout<<"s="<<s<<endl;
//验证赋值误差
int il,is;
il=l;
is=s;
cout<<"il="<<il<<endl;
cout<<"is="<<is<<endl;
}
#include <iostream> using namespace std;
main()
{
//变量声明
char c;
double x,y;
//测试自增
cout<<"++E and E++ :"<<endl;
c='B';
cout<<"c="<<++c<<endl; //输出c=C
c='B';
cout<<"c="<<c++<<endl; //输出c=B
x=1.5;
y=5+ ++x; //加号后的空格不能少
cout<<"y="<<y<<endl; //输出y=7.5
x=1.5;
y=5+x++;
cout<<"y="<<y<<endl; //输出y=6.5
cout<<"--------------------"<<endl;
//测试自减
cout<<"--E and E-- :"<<endl;
c='B';
cout<<"c="<<--c<<endl; //输出c=A
c='B';
cout<<"c="<<c--<<endl; //输出c=B
x=1.5;
y=5+--x;
cout<<"y="<<y<<endl; //输出y=5.5
x=1.5;
y=5+x--;
cout<<"y="<<y<<endl; //输出y=6.5
}
#include <iostream> using namespace std;
main()
{
int a=3, b=2;
//输出关系表达式
cout<<a<b<<endl;
cout<<(a<b)<<(a>b)<<(a>=b)<<(a==b)<<(a!=b)<<endl;
bool flag=2*a<b+10;
cout<<"flag="<<flag;
}
#include <iostream> using namespace std;
main()
{
float a=3.5,b=2.1,c=0;
cout<<"a="<<a<<" b="<<b<<" c="<<c<<endl;
//与运算
cout<<"a&&b="<<(a&&b)<<endl;//输出1
cout<<"a&&c="<<(a&&c)<<endl;//输出0
//或运算
cout<<"a||b="<<(a||b)<<endl;//输出1
cout<<"a||c="<<(a||c)<<endl;//输出1
//非运算
cout<<"!a="<<!a<<endl<<"!c="<<!c<<endl;//输出0 1
//关系运算和逻辑运算
bool flag=a>=0 && a<=5; //变量a在[0,5]区间内
cout<<"a=>0 && a<=5="<<flag<<endl;//输出1
//算术运算、关系运算和逻辑运算
cout<<"a+5>2*b+2||a<b+3="<<(a+5>2*b+2||a<b+3)<<endl;//输出1
}
#include <iostream> using namespace std;
main()
{
//按位与运算
cout<<"24&12="<<(24&12)<<endl;
//按位异或运算
cout<<"24^12="<<(24^12)<<endl;
//按位或运算
cout<<"24|12="<<(24|12)<<endl;
//按位取反运算
cout<<"~24="<<(~24)<<endl;
//左移位运算
cout<<"5<<3="<<(5<<3)<<endl;
cout<<"-5<<3="<<(-5<<3)<<endl;
//右移位运算
cout<<"5>>3="<<(5>>3)<<endl;
cout<<"-5>>3="<<(-5>>3)<<endl;
}
#include <iostream> using namespace std;
main()
{
int a=1,b=1,c=3;
//显示a,b,c的值
cout<<"a="<<a<<" b="<<b<<" c="<<c<<endl;
//计算显示(1) b+=a+2*c%5; 的结果
b+=a+2*c%5; //相当于表达式语句 b=b+(a+2*c%5);
cout<<"(1) b="<<b<<endl;
//计算显示(2) a<<=c-2*b; 的结果
a=1,b=1,c=3;
a<<=c-2*b; // 相当于表达式语句 a=a<<(c-2*b);
cout<<"(2) a="<<a<<endl;
//计算显示(3) a*=b=c=3;的结果
a=1,b=1,c=3;
a*=b=c=3; //相当于语句组 c=3;b=c;a=a*b;
cout<<"(3) a="<<a<<" b="<<b<<" c="<<c<<endl;
//计算显示(4) a+=b+=c;的结果
a=1,b=1,c=3;
a+=b+=c; //相当于语句组 b=b+c; a=a+b;
cout<<"(4) a="<<a<<" b="<<b<<" c="<<c<<endl;
//计算显示(5) a-=b=++c+2;的结果
a=1,b=1,c=3;
a-=b=++c+2; //相当于语句组 ++c;b=b+c+2;a=a-b;
cout<<"(5) a="<<a<<" b="<<b<<" c="<<c<<endl;
}
#include <iostream> using namespace std;
main()
{
//用 sizeof 计算各类种常量的字节长度
cout<<"sizeof('$')="<<sizeof('$')<<endl;
cout<<"sizeof(1)="<<sizeof(1)<<endl;
cout<<"sizeof(1.5)="<<sizeof(1.5)<<endl;
cout<<"sizeof(\"Good!\")="<<sizeof("Good!")<<endl;
//用sizeof 计算各类型变量的字节长度
int i=100;
char c='A';
float x=3.1416;
double p=0.1;
cout<<"sizeof(i)="<<sizeof(i)<<endl;
cout<<"sizeof(c)="<<sizeof(c)<<endl;
cout<<"sizeof(x)="<<sizeof(x)<<endl;
cout<<"sizeof(p)="<<sizeof(p)<<endl;
//用sizeof 计算表达式的字节长度
cout<<"sizeof(x+1.732)="<<sizeof(x+1.732)<<endl;
//用 sizeof 计算各类型的字节长度
cout<<"sizeof(char)="<<sizeof(char)<<endl;
cout<<"sizeof(int)="<<sizeof(int)<<endl;
cout<<"sizeof(float)="<<sizeof(float)<<endl;
cout<<"sizeof(double)="<<sizeof(double)<<endl;
//用sizeof 计算数组的字节长度
char str[]="This is a test.";
int a[10];
double xy[10];
cout<<"sizeof(str)="<<sizeof(str)<<endl;
cout<<"sizeof(a)="<<sizeof(a)<<endl;
cout<<"sizeof(xy)="<<sizeof(xy)<<endl;
//用sizeof 计算自定义类型的长度
struct st {
short num;
float math_grade;
float Chinese_grade;
float sum_grade;
};
st student1;
cout<<"sizeof(st)="<<sizeof(st)<<endl;
cout<<"sizeof(student1)="<<sizeof(student1)<<endl;
}
#include <iostream> using namespace std;
main()
{
//声明变量语句中使用顺序运算
int x, y;
//计算中使用顺序运算
x=50;
y=(x=x-5, x/5);
cout<<"x="<<x<<endl;
cout<<"y="<<y<<endl;
}
#include <iostream> using namespace std;
main()
{
//测试表达式类型的转换
int n=100,m;
double x=3.791,y;
cout<<"n*x="<<n*x<<endl;
//赋值类型转换
m=x;
y=n;
cout<<"m="<<m<<endl;
cout<<"y="<<y<<endl;
//强制类型转换
cout<<"int(x)="<<int(x)<<endl;
cout<<"(int)x="<<(int)x<<endl;
cout<<"int(1.732+x)="<<int(1.732+x)<<endl;
cout<<"(int)1.732+x="<<(int)1.723+x<<endl;
cout<<"double(100)="<<double(100)<<endl;
}
#include <iostream> using namespace std;
main()
{
float a,b,s;
cout<<"a b"<<endl;
cin>>a>>b; //利用cin从键盘上为变量 a,b 赋值
s=a;
if (a<b) {
s=b; //if语句中只有这一个语句,可省略花括号
}
s=s*s; //变量s中保存a,b中较大的一个数的平方
cout<<"s="<<s;
}
#include <iostream> using namespace std;
main()
{
int x,y;
cout<<"x=";
cin>>x;
if (x<=0) { //满足条件执行
y=2*x;
cout<<"y="<<y; //输出结果
}
else { //不满足条件执行
y=x*x;
cout<<"y="<<y; //输出结果
}
}
#include <iostream> using namespace std;
main()
{
int a,b,c;
int smallest;
cout<<"a b c"<<endl;
cin>>a>>b>>c;
if (a<=b) //外层条件语句
{
if (a<=c) //内层条件语句
smallest=a;
else
smallest=c;
}
else
{
if (b<=c) //内层条件语句
smallest=b;
else
smallest=c;
}
cout<<"Smallest="<<smallest<<endl;
}
#include <iostream> using namespace std;
main()
{
int score;
//从键盘上输入分数
cout<<"score=";
cin>>score;
//用带else if的条件语句判断处理
if (score<0 || score>100)
{
cout<<"The score is out of range!"<<endl;
}
else if (score>=90)
cout<<"Your grade is a A."<<endl;
else if (score>=80)
cout<<"Your grade is a B."<<endl;
else if (score>=70)
cout<<"Your grade is a C."<<endl;
else if (score>=60)
cout<<"Your grade is a D."<<endl;
else
cout<<"Your grade is a E."<<endl;
}
#include <iostream> using namespace std;
main()
{
int n;
cout<<"n=";
cin>>n;
if (n>=0 && n<=100 &&n%2==0)
cout<<"n="<<n<<endl;
else
cout<<"The "<<n<<" is out of range!"<<endl;
}
#include <iostream> using namespace std;
main()
{
int a,b,Max;
//输入数据
cout<<"a=";
cin>>a;
cout<<"b=";
cin>>b;
//找出较大值
Max=a>b?a:b;
cout<<"Max="<<Max<<endl;
}
#include <iostream> using namespace std;
main()
{
int a,b;
//输入数据
cout<<"a=";
cin>>a;
cout<<"b=";
cin>>b;
//除法判断
if (b!=0 && a%b==0) {
cout<<b<<" divides "<<a<<endl;
cout<<"a/b="<<a/b<<endl;
}
else
cout<<b<<" does not divide "<<a<<endl;
}
#include <iostream> using namespace std;
main()
{
//x,y 为操作数,c为运算符
int x,y,z;
char c1;
cin>>x>>c1>>y; //c1
//多路选择语句选择不同表达式计算语句
switch(c1) {
case '+':cout<<x<<"+"<<y<<"="<<x+y<<endl;
break;
case '-':cout<<x<<"-"<<y<<"="<<x-y<<endl;
break;
case '*':cout<<x<<"*"<<y<<"="<<x*y<<endl;
break;
case '/':cout<<x<<"/"<<y<<"="<<x/y<<endl;
break;
case '%':cout<<x<<"%"<<y<<"="<<x%y<<endl;
break;
default :cout<<"Wrong !"<<endl; //当不符合上述情况时执行本子句
}
}
#include<iostream.h>
float x=365.5; //声明全局变量
main() {
int x=1,y=2;
double w=x+y;
{
double x=1.414,y=1.732,z=3.14;
cout<<"inner:x="<<x<<endl;
cout<<"inner:y="<<y<<endl;
cout<<"inner:z="<<z<<endl;
cout<<"outer:w="<<w<<endl;
cout<<"::x="<<::x<<endl; //访问重名的全局变量
}
cout<<"outer:x="<<x<<endl;
cout<<"outer:y="<<y<<endl;
cout<<"outer:w="<<w<<endl;
//cout<<"inner:z="<<z<<endl;无效
cout<<"::x="<<::x<<endl; //访问重名的全局变量
}
#include<iostream.h>
main() {
//显示1,2,3...10
for(int i=1;i<=10;i++)
cout<<i<<" ";
cout<<endl;
//显示10,9,8...1
for(int j=10;j>=1;j--)
cout<<j<<" ";
cout<<endl;
//显示1,3,5...9
for(int k=1;k<=10;k=k+2)
cout<<k<<" ";
cout<<endl;
//显示ABC...Z
for(char c='A';c<='Z';c++)
cout<<c;
cout<<endl;
//显示0,0.1,0.2...1.0
for(float x=0;x<=1.0;x=x+0.1)
cout<<x<<" ";
cout<<endl;
//显示0,0.1,0.2...1.0
for(float x1=0;x1<=1.0+0.1/2;x1=x1+0.1)
cout<<x1<<" ";
cout<<endl;
//计算s=1+2+3...+100
int s=0;
for(int n=1;n<=100;n++)
s=s+n;
cout<<"s="<<s<<endl;
}
#include<iostream.h>
main()
{
//计算s=1+2+3...+100
int s=0,n=1;
while(n<=100) {
s=s+n;
n++;
}
cout<<"s="<<s<<endl;
//累加键盘输入的数据
double x,sum=0.0;
cout<<"x=";
cin>>x;
while(x!=0) {
sum+=x;
cout<<"x=";
cin>>x;
}
cout<<"sum="<<sum<<endl;
}
#include<iostream.h>
main()
{
//计算s=1+2+3...+100
int s=0,n=0;
do {
n++;
s+=n;
}while(n<100);
cout<<"s="<<s<<endl;
//累加键盘输入的数据
double x,sum=0.0;
do {
cout<<"x=";
cin>>x;
sum+=x;
} while(x!=0);
cout<<"sum="<<sum<<endl;
}
#include<iostream.h>
main()
{
//计算和打印打印乘法九九表
for (int i=1;i<=9;i++) {
cout<<i;
for (int j=1;j<=9;j++)
cout<<'\t'<<i<<"*"<<j<<"="<<i*j;
cout<<endl;
}
}
#include<iostream.h>
main()
{
int x,sum=0;
//定义标号L1
L1: cout<<"x=";
cin>>x;
if (x==-1)
goto L2; //无条件转移语句,转到L2语句处
else
sum+=x;
goto L1; //无条件转移语句,转到L1语句处
//定义标号L2
L2: cout<<"sum="<<sum<<endl;
}
#include<iostream.h>
main()
{
//累加键盘输入的数据
double x,sum=0.0;
while(1) {
cout<<"x=";
cin>>x;
if (x<=0) break;
sum+=x;
}
cout<<"sum="<<sum<<endl;
}
#include<iostream.h>
main()
{
int i;
for (i=1;i<=20;i++)
{
if (i%3==0) //能被 3 整除的整数,返回进行下次循环
continue;
cout<<i<<" ";
}
cout<<endl;
}
#include<iostream.h>
main()
{
//声明数组和变量
int a[5],i,sum;
double avg;
//从键盘上循环为数组赋值
for (i=0;i<5;i++) {
cout<<"a["<<i<<"]=";
cin>>a[i];
}
//直接显示数组元素
cout<<a[0]<<a[1]<<a[2]<<a[3]<<a[4]<<endl;
//利用for循环显示数组各元素的值
for (i=0;i<5;i++)
cout<<a[i]<<" ";
cout<<endl;
//计算数组元素之和,并显示计算结果
sum=a[0]+a[1]+a[2]+a[3]+a[4];
cout<<"sum="<<sum<<endl;
//利用循环计算数组的累加和
for (sum=0,i=0;i<5;i++)
sum+=a[i];
//显示累加和及平均值
cout<<"sum="<<sum<<endl;
avg=sum/5.0;
cout<<"avg="<<avg<<endl;
}
#include<iostream.h>
main()
{
int i,max,index,a[5];
//从键盘上为数组赋值
for (i=0;i<=4;i++)
{
cout<<"a["<<i<<"]=";
cin>>a[i];
}
// 利用循环遍历数组,找出最大值的元素及其下标
max=a[0];
for (i=0;i<=4;i++)
{
if (max<a[i])
{
max=a[i];
index=i;
}
}
cout<<"\nMax="<<max<<" index="<<index;
}
#include<iostream.h>
#define size 5
main()
{
//声明变量
int i,j;
float t,a[size];
//从键盘上为数组赋值
for (i=0;i<size;i++)
{
cout<<"a["<<i<<"]=";
cin>>a[i];
}
//对数组按从小到大顺序排序
for (i=0;i<size-1;i++)
for (j=i+1;j<size;j++)
if (a[i]>a[j])
{
t=a[i];
a[i]=a[j];
a[j]=t;
}
//显示排序结果
for (i=0;i<size;i++)
cout<<a[i]<<" ";
cout<<endl;
//输入要查找的数据
int value;
int found; //找到为1,否则为0
int low,high,mid;
for (i=1;i<=3;i++) {
cout<<"value=";
cin>>value;
//二分法查找数组a
found=0;
low=0;
high=size-1;
while(low<=high)
{
mid=(high+low)/2;
if (a[mid]==value)
{
found=1;
break;
}
if (a[mid]<value)
low=mid+1;
else
high=mid-1;
}
if (found)
cout<<"The valu found at:a["<<mid<<"]="<<a[mid]<<endl;
else
cout<<"The "<<value<<" is not found!"<<endl;
}
}
#include<iostream.h>
main()
{
//声明变量
int i,j;
float t,a[5];
//从键盘上为数组赋值
for (i=0;i<=4;i++)
{
cout<<"a["<<i<<"]=";
cin>>a[i];
}
//对数组按从大到小顺序排序
for (i=0;i<=3;i++)
for (j=i+1;j<=4;j++)
if (a[i]<=a[j])
{
t=a[i];
a[i]=a[j];
a[j]=t;
}
//显示排序结果
for (i=0;i<=4;i++)
cout<<a[i]<<" ";
}
#include<iostream.h>
main()
{
//声明二维数组及变量
int a[2][3],i,j;
//从键盘上为数组a赋值
for (i=0;i<2;i++)
for (j=0;j<3;j++)
{
cout<<"a["<<i<<"]["<<j<<"]=";
cin>>a[i][j];
}
//显示数组a
for (i=0;i<2;i++) {
for (j=0;j<3;j++)
{
cout<<a[i][j]<<" ";
}
cout<<endl;
}
//找出该数组的最大元素及其下标
int h,l,Max=a[0][0];
for (i=0;i<2;i++) {
for (j=0;j<3;j++)
{
if (Max<a[i][j]) {
Max=a[i][j];
h=i;
l=j;
}
}
}
cout<<"Max:"<<"a["<<h<<"]["<<l<<"]="<<a[h][l]<<endl;
}
#include<iostream.h>
main()
{
//声明字符数组和变量
char str[6];
int i;
//从键盘上输入字符串
cout<<"str=";
cin>>str;
cout<<str<<endl;
//按数组和下标变量两种方式显示字符数组
cout<<str<<endl;
for (i=0;i<6;i++)
cout<<str[i];
cout<<endl;
//字符串反向输出
for (i=5;i>=0;i--)
cout<<str[i];
cout<<endl;
//将字符数组变成大写字母后输出
for (i=0;i<=5;i++)
str[i]-=32; //小写字母转换成大写字母
cout<<str<<endl; //显示字符串
}
#include<iostream.h>
main()
{
//声明变量和指针变量
int a,b,c,*ip;
//指针变量ip指向变量a
a=100;
ip=&a; //使指针变量 ip 指向变量a
cout<<"a="<<a<<endl;
cout<<"*ip="<<*ip<<endl;
cout<<"ip="<<ip<<endl;
//指针变量ip指向变量b
ip=&b; //使指针变量 ip 指向变量b
b=200;
cout<<"b="<<b<<endl;
cout<<"*ip="<<*ip<<endl;
cout<<"ip="<<ip<<endl;
//指针变量ip指向变量c
ip=&c; //使指针变量 ip 指向变量b
*ip=a+b;
cout<<"c="<<c<<endl;
cout<<"*ip="<<*ip<<endl;
cout<<"ip="<<ip<<endl;
}
#include<iostream.h>
main()
{
//声明数组、变量和指针变量
int a[2][3],i,j;
int* ip;
//从键盘上为数组a赋值
for (i=0;i<2;i++) //为数组a赋值
for (j=0;j<3;j++)
{
cout<<"a["<<i<<"]["<<j<<"]=";
cin>>a[i][j];
}
//利用下标变量显示数组a
for (i=0;i<2;i++) {
for (j=0;j<3;j++)
{
cout<<a[i][j]<<" ";
}
cout<<endl;
}
//利用指针变量显示数组a
ip=&a[0][0];
for (i=0;i<2;i++) {
for (j=0;j<3;j++)
{
cout<<"a["<<i<<"]["<<j<<"]=";
cout<<ip<<" ";
cout<<*ip<<endl;
ip++;
}
}
}
#include<iostream.h>
main()
{
//声明数组、变量和指针变量
int a[]={1,2,3,4,5,6};
int *ip1,*ip2;
//测试指针的赋值运算
ip1=a;
ip2=ip1;
cout<<"*ip1="<<(*ip1)<<endl;
cout<<"*ip2="<<(*ip2)<<endl;
//测试指针的自增自减运算和组合运算
ip1++;
ip2+=4;
cout<<"*ip1="<<(*ip1)<<endl;
cout<<"*ip2="<<(*ip2)<<endl;
//测试指针变量之间的关系运算
int n=ip2>ip1;
cout<<"ip2>ip1="<<n<<endl;
cout<<"ip2!=NULL="<<(ip2!=NULL)<<endl;
//指针变量之间的减法
n=ip2-ip1;
cout<<"ip2-ip1="<<n<<endl;
}
#include<iostream.h>
main()
{
//声明字符型数组和指针变量
char str[10];
char *strip=str;
//输入输出
cout<<"str=";
cin>>str; //用字符数组输入字符串
cout<<"str="<<str<<endl;
cout<<"strip="<<strip<<endl;
cout<<"strip=";
cin>>strip; //用字符指针变量输入字符串
cout<<"str="<<str<<endl;
cout<<"strip="<<strip<<endl;
//利用指针变量改变其指向字符串的内容
*(strip+2)='l';
cout<<"str="<<str<<endl;
cout<<"strip="<<strip<<endl;
//动态为字符型指针变量分配内存
strip=new char(100);
cout<<"strip=";
cin>>strip; //用字符指针变量输入字符串
cout<<"str="<<str<<endl;
cout<<"strip="<<strip<<endl;
}
#include<iostream.h>
main()
{
// 声明用于存放运动员号码的数组
int h[]={1001,1002,1003,1004};
// 声明用于存放运动员成绩的数组
float x[]={12.3,13.1,11.9,12.1};
//声明用于存放运动姓名的字符型指针数组
char *p[]={"Wang hua","Zhang jian","Li wei","Hua ming"};
//i,j,it是用做循环控制变量和临时变量
int i,j,it;
//ft 用做暂存变量
float ft;
//pt为字符型指针变量用做暂存指针变量
char *pt;
//用选择法对数组x进行排序,并相应调整数组h和p中的数据
for (i=0;i<=3;i++)
for (j=i+1;j<=3;j++)
if (x[i]>=x[j]) {
ft=x[i],x[i]=x[j],x[j]=ft;
it=h[i],h[i]=h[j],h[j]=it;
pt=p[i],p[i]=p[j],p[j]=pt;
}
//以下打印排序结果
for (i=0;i<=3;i++)
cout<<h[i]<<" ,"<<p[i]<<" ,"<<x[i]<<endl;
}
#include<iostream.h>
main()
{
//声明指针数组
char *colors[]={"Red","Blue","Yellow","Green"};
//指向指针的指针变量
char **pt;
//通过指向指针的变量访问其指向的内容
pt=colors;
for (int i=0;i<=3;i++) {
cout<<"pt="<<pt<<endl;
cout<<"*pt="<<*pt<<endl;
cout<<"**pt="<<**pt<<endl;
pt++;
}
}
#include<iostream.h>
main()
{
//定义结构类型
struct books
{
char title[20];
char author[15];
int pages;
float price;
} ;
//声明结构变量
struct books Zbk={"VC++ ","Zhang",295,35.5};
books Wbk;
//对结构变量的输出
cout<<"Zbk:"<<endl;
cout<<Zbk.title <<endl;
cout<<Zbk.author<<endl;
cout<<Zbk.pages<<endl;
cout<<Zbk.price<<endl;
cout<<"--------------------"<<endl;
//对结构成员的运算
Zbk.pages+=10;
Zbk.price+=0.5;
cout<<"Zbk.pages="<<Zbk.pages<<endl;
cout<<"Zbk.price="<<Zbk.price<<endl;
cout<<"--------------------"<<endl;
//对结构变量的输入输出
cout<<"Wbk.title =";
cin>>Wbk.title;
cout<<"Wbk.author=";
cin>>Wbk.author;
cout<<"Wbk.pages=";
cin>>Wbk.pages;
cout<<"Wbk.price=";
cin>>Wbk.price;
cout<<"Wbk:"<<endl;
cout<<Wbk.title <<endl;
cout<<Wbk.author<<endl;
cout<<Wbk.pages<<endl;
cout<<Wbk.price<<endl;
cout<<"-----------