??xml version="1.0" encoding="utf-8" standalone="yes"?> Text区域用来储存指o(h)(instruction)Q来告诉E序每一步的操作。Global Data用于存放全局变量Qstack用于存放局部变量,heap用于存放动态变?(dynamic variable. E序利用mallocpȝ调用Q直接从内存?sh)?f)dynamic variable开辟空??span style="margin: 0px; padding: 0px; color: #ff0000;">Text?span style="margin: 0px; padding: 0px; color: #ff0000;">Global data在进E一开始的时候就定?jin),q在整个q程中保?span style="margin: 0px; padding: 0px; color: #ff0000;">固定大小?/span> Stack(?span style="margin: 0px; padding: 0px; color: #000000;">)?span style="margin: 0px; padding: 0px; color: #ff0000;">stack frame为单位。当E序调用函数的时候,比如main()函数中调用inner()函数Qstack?x)向下增长一个stack frame。Stack frame中存储该函数?span style="margin: 0px; padding: 0px; color: #ff0000;">参数?span style="margin: 0px; padding: 0px; color: #ff0000;">局部变?/span>Q以?qing)该函数?span style="margin: 0px; padding: 0px; color: #ff0000;">q回地址(return address)。此Ӟ计算机将控制权从main()转移到inner()Qinner()函数处于Ȁz?/span>(active)状态。位于Stack最下方的frame和Global Data构成了(jin)当前的环?context)。激zd数可以从中调用需要的变量。典型的~程语言都只允许你用位于stack最下方的frame Q而不允许你调用其它的frame (q也W合stackl构“先进后出”的特征。但也有一些语a允许你调用stack的其它部分,相当于允怽在运行inner()函数的时候调用main()中声明的局部变量,比如Pascal)。当函数又进一步调用另一个函数的时候,一个新的frame?x)l增加到stack下方Q控制权转移到新的函C。当Ȁzd?span style="margin: 0px; padding: 0px; color: #ff0000;">q回的时候,?x)从stack?span style="margin: 0px; padding: 0px; color: #ff0000;">弹出(popQ就是读取ƈ删除)该frameQƈҎ(gu)frame中记录的q回地址Q将控制权交l返回地址所指向的指?/span>(比如从inner()函数中返回,l箋(hu)执行main()中赋值给main2的操??/span> 下图是stack在运行过E中的变化,头表示stack增长的方向,每个方块代表一个stack frame。开始的时候我们有一个ؓ(f)main()服务的frameQ随着调用inner()Q我们ؓ(f)inner()增加一个frame。在inner()q回Ӟ我们再次只有main()的frameQ直到最后main()q回Q其q回地址为空Q所以进E结束?br /> 在进E运行的q程中,通过调用和返回函敎ͼ控制?/span>不断在函数间转移。进E可以在调用函数的时候,原函数的stack frame中保存有在我们离开时的状态,qؓ(f)新的函数开辟所需的stack frameI间。在调用函数q回Ӟ该函数的stack frame所占据的空间随着stack frame的弹?gu)清I。进E再ơ回到原函数的stack frame中保存的状态,q根据返回地址所指向的指令l执行。上面过E不断l,stack不断增长或减,直到main()q回的时候,stack完全清空Q进E结束?/span> 当程序中使用malloc的时候,heap(?span style="margin: 0px; padding: 0px; color: #000000;">)?/span>向上增长Q其增长的部分就成ؓ(f)malloc从内存(sh)分配的空间。malloc开辟的I间?x)一直存在,直到我们用freepȝ调用来释放,或者进E结束。一个经典的错误?span style="margin: 0px; padding: 0px; color: #ff0000;">内存泄漏(memory leakage), 是指我们没有释放不再用的heapI间Q导致heap不断增长Q而内存可用空间不断减?/span> ׃stack和heap的大则?x)随着q程的运行增大或者变,当stack和heap增长C者相遇时候,也就是内存空间图中的蓝色区域(unused area)完全消失的时候,q程?x)出?span style="margin: 0px; padding: 0px; color: #ff0000;">栈溢?/span>(stack overflow)的错误,Dq程l止。在C计算ZQ内怸般都?x)?f)q程分配_多的蓝色区域Q如果我们即时清理的话,stack overflow是可以避免的。但是,在进行一些矩阵运的时候,׃所需的内存很大,依然可能出现stack overflow的情c(din)一U解x(chng)式是增大内核分配l每个进E的内存I间。如果依然不能解决问题的话,我们需要增加物理内存?br />
当程序文件运行ؓ(f)q程的时候,q程在内存(sh)得到I间(q程自己的小戉K)。每个进E空间按照如下方式分Z同区?
内存I间
stack变化
堆和栈的区别Q?br />
2.1甌方式
stack:
ql自动分配?nbsp; 例如Q声明在函数中一个局部变?nbsp; int b; pȝ自动在栈中ؓ(f)b开辟空
?nbsp;
heap:
需要程序员自己甌Qƈ指明大小Q在c中malloc函数
如p1 = (char *)malloc(10);
在C++中用newq算W?nbsp;
如p2 = new char[10];
但是注意p1、p2本n是在栈中的?nbsp;
2.2
甌后系l的响应
栈:(x)只要栈的剩余I间大于所甌I间Q系l将为程序提供内存,否则报异常提示栈溢
出?nbsp;
堆:(x)首先应该知道操作pȝ有一个记录空闲内存地址的链表,当系l收到程序的甌Ӟ
?x)遍历该链表Q寻扄一个空间大于所甌I间的堆l点Q然后将该结点从I闲l点链表
中删除,q将该结点的I间分配l程序,另外Q对于大多数pȝQ会(x)在这块内存空间中?nbsp;
首地址处记录本ơ分配的大小Q这P代码中的delete语句才能正确的释放本内存I间?nbsp;
另外Q由于找到的堆结点的大小不一定正好等于申L(fng)大小Q系l会(x)自动的将多余的那?nbsp;
分重新放入空闲链表中?nbsp;
2.3甌大小的限?nbsp;
栈:(x)在Windows?栈是向低地址扩展的数据结构,是一块连l的内存的区域。这句话的意
思是栈顶的地址和栈的最大容量是pȝ预先规定好的Q在WINDOWS下,栈的大小?MQ也?nbsp;
的说?MQM是一个编译时q定的常数Q,如果甌的空间超q栈的剩余空间时Q将
提示overflow。因此,能从栈获得的I间较小?nbsp;
堆:(x)堆是向高地址扩展的数据结构,是不q箋(hu)的内存区域。这是由于系l是用链表来存储
的空闲内存地址的,自然是不q箋(hu)的,而链表的遍历方向是由低地址向高地址。堆的大?nbsp;
受限于计机pȝ中有效的虚拟内存。由此可见,堆获得的I间比较灉|Q也比较大?nbsp;
2.4甌效率的比较:(x)
栈由pȝ自动分配Q速度较快。但E序员是无法控制的?nbsp;
堆是由new分配的内存,一般速度比较慢,而且Ҏ(gu)产生内存片,不过用v来最方便.
另外Q在WINDOWS下,最好的方式是用VirtualAlloc分配内存Q他不是在堆Q也不是在栈?nbsp;
直接在进E的地址I间中保留一块内存,虽然用v来最不方ѝ但是速度快,也最灉|?nbsp;
2.5堆和栈中的存储内?nbsp;
栈:(x) 在函数调用时Q第一个进栈的是主函数中后的下一条指令(函数调用语句的下一条可
执行语句Q的地址Q然后是函数的各个参敎ͼ在大多数的C~译器中Q参数是由右往左入?nbsp;
的,然后是函C的局部变量。注意静(rn)态变量是不入栈的?nbsp;
当本ơ函数调用结束后Q局部变量先出栈Q然后是参数Q最后栈指针指向最开始存的地
址Q也是dC的下一条指令,E序p点l运行?nbsp;
堆:(x)一般是在堆的头部用一个字节存攑֠的大。堆中的具体内容q序员安排?nbsp;
2.6存取效率的比?nbsp;
char s1[] = "aaaaaaaaaaaaaaa";
char *s2 = "bbbbbbbbbbbbbbbbb";
aaaaaaaaaaa是在q行时刻赋值的Q?nbsp;
而bbbbbbbbbbb是在~译时就定的;
但是Q在以后的存取中Q在栈上的数l比指针所指向的字W串(例如?快?
2.7结Q?nbsp;
堆和栈的区别可以用如下的比喻来看出:(x)
使用栈就象我们去饭馆里吃饭,只管点菜Q发出申P(j)、付钱、和吃(使用Q,吃饱?jin)?nbsp;
赎ͼ不必理会(x)切菜、洗菜等准备工作和洗、刷锅等扫尾工作Q他的好处是快捷Q但是自
由度?nbsp;
使用堆就象是自己动手做喜Ƣ吃的菜_(d)比较ȝ(ch)Q但是比较符合自q口味Q而且自由
度大?nbsp; (l典Q?
]]>
// q个*代表的值由后面的参数列表中的整数型(int)值给?br />
// 例如Q?/span>
printf("%.*s\n", 1, "abc"); // 输出a
printf("%.*s\n", 2, "abc"); // 输出ab
printf("%.*s\n", 3, "abc"); // 输出abc >3是一L(fng)效果 因ؓ(f)输出cdtype = sQ遇?\0'?x)结?br />
]]>
{
int M,b;
int N[100],c=0;
scanf("%d%d",&b,&M);//输入q制b(2~10),要{化ؓ(f)bq制的正整数M(十进?
while(M)
{
N[c++]=M%b;
M=M/b;
}
for(int i=c-1;i>=0;i--)
printf("%d",N[i]);
printf("\n");
return 0;
}
]]>
#include<math.h>
int main()
{
char M[100]={0};
int N=0;
gets(M);
int len=strlen(M);
for(int i=0;i<len;i++)
{
N+=(M[i]-'0') * pow(2.0,len-i-1);
}
printf("%d\n",N);
return 0;
}
]]>
代码如下Q?br />
#define N 10
int Maxcom(int a, int b)
{
while(a!=b)
{
if(a>b)
a=a-b;
else if(b>a)
b=b-a;
}
return a;
}
int main()
{
int a[N][N];
int i,j,max;
for(i=0;i<5;i++)
{
for(j=0;j<5;j++)
{
if(i==1 && j==1)
a[i][j]=1;
else if( i>0 && j>0)
{
max = Maxcom(i,j);
if(max == 1)
a[i][j]=1;
else
a[i][j]=0;
}
else
a[i][j]=0;
}
}
for(i=0;i<5;i++)
{
for(j=0;j<5;j++)
printf("%d ",a[i][j]);
printf("\n");
}
printf("\n");
return 0;
}
]]>
for(j=0;j<N;j++)
for(k=0,c[i][j] = 0.0;k<N;k++)
c[i][j] +=a[i][k] * b[k][j];
二维数组的分配:(x)
#include<stdlib.h>
int **malloc2d(int r, int c) //二维数组分配函数
{
int i;
int **t = (int **)malloc(r * sizeof(int *));
for(i=0;i<r;i++)
t[i] = (int *)malloc(c * sizeof(int));
return t;
}
int main()
{
int i,j;
int **a =malloc2d(3,3);
for(i=0;i<3;i++)
for(j=0;j<3;j++)
a[i][j]=i+j;
for(i=0;i<3;i++)
{
for(j=0;j<3;j++)
printf("%d ",a[i][j]);
printf("\n");
}
return 0;
}
l合计算二维数组怹的乘U?br />代码如下Q?br />
#include<stdlib.h>
int **malloc2d(int r, int c)
{
int i;
int **t = (int **)malloc(r * sizeof(int *));
for(i=0;i<r;i++)
t[i] = (int *)malloc(c * sizeof(int));
return t;
}
int main()
{
int i,j,k;
int **a =malloc2d(3,3);
int **b =malloc2d(3,3);
int **c =malloc2d(3,3);
for(i=0;i<3;i++)
{
for(j=0;j<3;j++)
{
a[i][j]=i+j;
b[i][j]=i+j;
}
}
for(i=0;i<3;i++)
{
for(j=0;j<3;j++)
printf("%d ",a[i][j]);
printf("\n");
}
printf("\n");
for(i=0;i<3;i++)
for(j=0;j<3;j++)
for(k=0,c[i][j] = 0.0;k<3;k++)
c[i][j] +=a[i][k] * b[k][j];
for(i=0;i<3;i++)
{
for(j=0;j<3;j++)
printf("%d ",c[i][j]);
printf("\n");
}
return 0;
}
]]>
#include<stdio.h>
#include<stdlib.h>
int compare(const void * a,const void * b)
{
return *(int*)a - *(int*)b;
}
int main()
{
int a[20],i;
for(i=0;i<10;i++)
{
scanf("%d",&a[i]);
}
qsort(a,10,sizeof(int),compare);
for(i=0;i<10;i++)
printf("%d ",a[i]);
return 0;
}
]]>
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define Nmax 1000
#define Mmax 10000
char buf[Mmax]; int M=0;
int compare(const void *i, const void *j)
{
return strcmp(*(char **)i, *(char **)j);
}
int main()
{
int i, N;
char *a[Nmax];
for(N=0; N<Nmax; N++)
{
a[N]= &buf[M];
if(scanf("%s", a[N]) == EOF) break;
M+=strlen(a[N])+1;
}
qsort(a,N,sizeof(char*),compare); //四个参数分别代表Q待排序的数l首地址Q数l中待排序的元素数量Q各元素占用的空_(d)排序函数Q确定排序顺序)(j)
for(i=0;i<N;i++)
printf("%s\n",a[i]);
return 0;
}
]]>#include<stdio.h>
#include<string.h>
int main()
{
FILE *fp;
char pathName[20],txt1[100]={'\0'},txt2[20]={'\0'};
int fileLen;
printf("Please type the path name of the file\n");
scanf("%s",pathName);
fp=fopen(pathName,"w");
printf("Please input a string to this file\n");
scanf("%s",txt1);
fileLen=strlen(txt1);
fwrite(txt1,fileLen,1,fp);
fclose(fp);
printf("The file has been saved\n");
printf("The content of teh file: %s is\n",pathName);
fp=fopen(pathName,"r");
fread(txt2,fileLen,1,fp);
printf("%s\n",txt2);
return 0;
}
]]>
每次选取质量最的子装入船(用冒泡排序算法解冻I(j)Q代码如下:(x)
#include<stdio.h>
#include<stdlib.h>
void sort(int w[],int t[],int n)//w[]存放每个集装q质量Qt[]存放w[]的下?/span>
{
int i,j,tmp;
int *w_tmp=(int *)malloc(sizeof(int)*n);//开辟一个(f)时数l,存放w[]的内容,用于排序
for(i=0;i<n;i++)
t[i]=i;//初始化数lt
for(i=0;i<n;i++)
w_tmp[i]=w[i];
for(i=0;i<n-1;i++)
for(j=0;j<n-i-1;j++)//冒(chng)排序实现
if(w_tmp[j]>w_tmp[j+1])
{
tmp=w_tmp[j];
w_tmp[j]=w_tmp[j+1];
w_tmp[j+1]=tmp;
tmp=t[j];
t[j]=t[j+1];
t[j+1]=tmp;
}
}
void loading(int x[],int w[],int c,int n)
{
int i,s=0;
int *t=(int*)malloc(sizeof(int)*n);//动态开辟一个(f)时数l,存放w[]的下?/span>
sort(w,t,n);
for(i=0;i<n;i++)
x[i]=0;
for(i=0;i<n && w[t[i]]<=c;i++){
x[t[i]]=1; //第t[i]个集装箱装入货船?/span>
c=c-w[t[i]]; //变量c中存放货船的剩余载质?/span>
}
}
int main()
{
int x[5],w[5],c,i;
printf("Iput the maximum loading of the sheep\n");
scanf("%d",&c);
printf("Iput the weight of Five box\n");
for(i=0;i<5;i++)
scanf("%d",&w[i]);
loading(x,w,c,5);
printf("The following boxes will be loaded\n");
for(i=0;i<5;i++)
{
if(x[i]==1) printf("BOX:%d ",i);
}
return 0;
}
]]>
#include<string.h>
char* strins(char* str1,char* str2,int pos)
{
int s_len;
int d_len;
int i,j;
pos--;
s_len=strlen(str1);
d_len=strlen(str2);
for(i=s_len+1;i>=pos;i--) /*I出str2的空?/span>*/
str1[i+d_len]=str1[i];
for(j=pos;str2[j-pos]!='\0';j++) /*字W串str2插入str1中的特定位置*/
str1[j]=str2[j-pos];
return str1;
}
void main()
{
char string1[200];
char string2[100];
int pos;
printf("误入初始字W串:");
gets(string1);
printf("误入插入字W串:");
gets(string2);
printf("误入插入位|?");
scanf("%d",&pos);
strins(string1,string2,pos);
printf("插入后的字符串是%s\n",string1);
}
]]>
#include<string.h>
void IntToStr(int n);
char str[80]={0};
void main()
{
int num;
printf("input an integer number:");
scanf("%d",&num);
IntToStr(num);
printf("The string is:%s\n",str);
}
void IntToStr(int n)
{
int i;
if(n==0)//整数?Ӟ递归l束
return;
for(i=strlen(str)-1;i>=0;i--) //字W串整个往后移一个字W?/span>
str[i+1]=str[i];
str[0]=n%10+0x30; //该数的个位数{换成字符攑֜字符数组的第一个元素的位置Q?0x30表示十六q制?Q其实可以不?/span>
IntToStr(n/10);//该数的商,即除个位外的其他数通过递归转换
}
//递归q程Q例如输入n=148,那么W一ơ递归Ӟstr[0]存放的数?,n/10=14Q得到第二次递归的数?4Q?br />//8原先存储在str[0]Q但W二ơ递归向后Ud一个字W,变成存在str[1]内,?存在str[0]内;
//W三ơ递归Ӟ同理可知8攑֜str[2],4攑֜str[1],?攑֜str[0]Q这样就?48转换为字W串?/span>
]]>
用C语言代码表示如下Q?br />
long F(int n);
void main()
{
int i;
for(i=1;i<=40;i++)
{
printf("F(%2d)=%-9ld",i,F(i));
if(i%4==0)
printf("\n");
}
}
long F(int n)//求第n的?/span>
{
if(n<=2)
return (1);
return(F(n-1)+F(n-2));
}
]]>
依次比较盔R的两个数Q将数攑֜前面Q大数放在后面。即在第一:(x)首先比较W?个和W?个数Q将数攑։Q大数放后。然后比较第2个数和第3个数Q将数攑։Q大数放后,如此l箋(hu)Q直x(chng)较最后两个数Q将数攑։Q大数放后。至此第一结束,最大的数放C(jin)最后。在W二:(x)仍从W一Ҏ(gu)开始比较(因ؓ(f)可能׃W?个数和第3个数的交换,使得W?个数不再于W?个数Q,小数放前,大数攑Q一直比较到倒数W二个数Q倒数W一的位|上已经是最大的Q,W二结束,在倒数W二的位|上得到一个新的最大数Q其实在整个数列中是W二大的敎ͼ(j)。如此下去,重复以上q程Q直x(chng)l完成排序。需要用二重循环排序?br />Example:
#include<stdio.h>
int main()
{
int i,j,temp,tag;
int a[11]; //数组W?位空?br />
for(i=1;i<=10;i++)
scanf ("%d,",&a[i]);
for(j=1;j<=10;j++)
{
tag=1;
for (i=1;i<=10-j;i++)
{
if (a[i]>a[i+1])
{
temp=a[i];
a[i]=a[i+1];
a[i+1]=temp;
tag=0;
}
}
if(1==tag)
{
break;
}
}
for(i=0;i<10;i++)
printf("%5d",a[i]);
return 0;
}
以下是选择排序法:(x)
每次外@环先定位元素的标iD录到KQ认为a[k]是最|W一轮比较时Q若遇到比a[k]更小的数Q则交换两数的下标,׃面的if语句q行交换处理?br />q样W一轮就选出?jin)最的敎ͼW二轮,同理选出ơ小的数排在最的数后面。如果是输入10个数Q那么进?轮排序后可完成整个排序q程?br />
void main()
{
int i,j,t,a[10],k;
printf("input 10 numbers:\n");
for(i=0;i<10;i++)
scanf("%d",&a[i]);
for(i=0;i<9;i++)//q里也要注意i=0;i<9;
{
k=i;
for(j=i+1;j<10;j++)
if(a[k]>a[j])
k=j;
if(k!=i)//如果k不等于iQ改变(sh)(jin)Q则交换两个数的位置
{
t=a[i];
a[i]=a[k];
a[k]=t;
}
}
for(i=0;i<10;i++)//最后输出已l排好序的数
printf("%5d",a[i]);
}
PSQ大一刚开始接触这两个排序法Ӟ感觉有点乱,现在回过头来仔细看,思\清晰?jin)不。时d过ȝ知识Q进行整理,再认识,很重要呀?-D
]]>原理?qing)其详细证?/span>
设两Cؓ(f)a、b(b<a)Q用gcd(a,b)表示aQb的最大公U数Qr=a mod b 为a除以b以后的余敎ͼ辗{盔R法即是要证明gcd(a,b)=gcd(b,r)?
W一步:(x)令c=gcd(a,b)Q则设a=mcQb=nc
W二步:(x)Ҏ(gu)前提可知r =a-kb=mc-knc=(m-kn)c
W三步:(x)Ҏ(gu)W二步结果可知c也是r的因?
W四步:(x)可以断定m-kn与n互素【否则,可设m-kn=xdQn=ydQ?d>1)Q则m=kn+xd=kyd+xd=(ky+x)dQ则a=mc=(ky+x)dcQb=nc=ycdQ故a与b最大公U数成ؓ(f)cdQ而非c?
从而可知gcd(b,r)=cQ而gcd(a,b)=gcd(b,r)?
证毕?br />
用C表示则:(x)
int gcd(int a,int b)
{
int temp;
if(a<b)/*交换两个敎ͼ使大数放在a?/
{
temp=a;
a=b;
b=temp;
}
while(b!=0)/*利用辗除法,直到b?为止*/
{
temp=a%b;
a=b;
b=temp;
}
return a;
}
]]>
2 int Maxcommonfactor(int a,int b);
3 void main()
4 {
5 int a,b,c;
6 printf("input two integer number:");
7 scanf("%d%d",&a,&b);
8 c=Maxcommonfactor(a,b);
9 if(c!=-1)
10 printf("The biggest common factor of %d and %d is %d\n",a,b,c);
11 else
12 printf("The biggest common factor of %d and %d isn't exist\n",a,b);
13 }
14 int Maxcommonfactor(int a,int b)
15 {
16 if(a<=0||b<=0)
17 return(-1);
18 while(a!=b)
19 {
20 if(a>b)
21 a=a-b;
22 else if(b>a)
23 b=b-a;
24 }
25 return(a);//q回的gؓ(f)最大公U数
26 }
27
28
]]>