??xml version="1.0" encoding="utf-8" standalone="yes"?>
ȝ自己写程序时的变量,函数命名风格Q?br> example :
pointer --> p_+varname; int *p_ivalue = NULL;
typedef --> t_+typenam; typedef struct name t_name
globle variable --> g_+typevarname int g_ivalue = 0;
member variable --> m_+typevarname int m_ivalue = 0;
static variable --> s_+typevarname static int s_ivalue = 0;
temp variable --> typevarname int ivalue = 0;
string varable --> str_varname string str_name;
const string varalbe --> cstr_varname const string cstr_name
function style :
extern int name_name_name(type var_name,...)
#define 只是用来做文本替换的
例如Q?/p>
#define Pi 3.1415926
float angel;
angel=30*Pi/180;
那么Q当E序q行~译的时?~译器会首先?“#define Pi 3.1415926”以后的,所有代码中?#8220;Pi”全部换成 “3.1415926”
然后再进行编译?/p>
我查C个讲const?define的差别的帖子Q里面谈到const?define最大的差别在于Q前者在堆栈分配了空_而后者只是把具体数值直接传递到目标变量|了。或者说Qconst的常量是一个Run-Time的概念,他在E序中确实实的存在q可以被调用、传递。?define帔R则是一个Compile-Time概念Q它的生命周期止于编译期Q在实际E序中他只是一个常数、一个命令中的参敎ͼ没有实际的存在?
const帔R存在于程序的数据D,#define帔R存在于程序的代码Dc?/font>
至于两者的优缺点,要看具体的情况了。一般的常数应用Q笔者个?define是一个更好的选择Q?/font>
i.从run-time的角度来看,他在I间上和旉上都有很好优ѝ?/font>
ii.从compile-time的角度来看,cMm=t*10的代码不会被~译器优化,t*10的操作需要在run-time执行。?define的常量会被合qӞ在上例中T*10被0x82取代Q?/font>
但是Q如果你需要粗鲁的修改常数的|那就得用const了,因ؓ后者在E序中没有实际的存在。(其实应该说修Ҏ(gu)据段比代码段要简单^_^Q?/font>
有关#define的用?/font>
1.单的define定义
#define MAXTIME 1000
E序中遇?/span>MAXTIME׃当作1000来处?/span>.
一个简单的MAXTIME定义好了,它代?/span>1000Q如果在E序里面?/span>
if(i<MAXTIME){.........}
~译器在处理q个代码之前会对MAXTIMEq行处理替换?/span>1000?/span>
q样的定义看hcM于普通的帔R定义CONSTQ但也有着不同Q因?/span>define的定义更像是单的文本替换Q而不是作Z个量来用,q个问题在下面反映的ؓH出?/span>
一、typedef的用?/strong>
在C/C++语言中,typedef常用来定义一个标识符及关键字的别名,它是语言~译q程的一部分Q但它ƈ不实际分配内存空_实例像:
typedef int INT;
typedef int ARRAY[10];
typedef (int*) pINT;
typedef可以增强E序的可L,以及标识W的灉|性,但它也有“非直观?#8221;{缺炏V?/p>
二?define的用?/strong>
#defineZ宏定义语句,通常用它来定义常?包括无参量与带参?Q以及用来实现那?#8220;表面似和善、背后一长串”的宏Q它本nq不在编译过E中q行Q而是在这之前(预处理过E?已l完成了Q但也因此难以发现潜在的错误及其它代码维护问题,它的实例像:
#define INT int
#define TRUE 1
#define Add(a,b) ((a)+(b));
#define Loop_10 for (int i=0; i<10; i++)
在Scott Meyer的Effective C++一书的条款1中有关于#define语句弊端的分析,以及好的替代Ҏ(gu)Q大家可参看?/p>
三、typedef?define的区?/strong>
从以上的概念便也能基本清楚,typedef只是Z增加可读性而ؓ标识W另L新名U?仅仅只是个别?Q?define原本在C中是Z定义帔RQ到了C++Qconst、enum、inline的出C它也渐渐成ؓ了v别名的工兗有时很Ҏ(gu)搞不清楚与typedef两者到底该用哪个好Q如#define INT intq样的语句,用typedef一样可以完成,用哪个好呢?我主张用typedefQ因为在早期的许多C~译器中q条语句是非法的Q只是现今的~译器又做了扩充。ؓ了尽可能地兼容,一般都遵@#define定义“可读”的常量以及一些宏语句的Q务,而typedef则常用来定义关键字、冗长的cd的别名?/p>
宏定义只是简单的字符串代?原地扩展)Q而typedef则不是原地扩展,它的新名字具有一定的装性,以致于新命名的标识符h更易定义变量的功能。请看上面第一大点代码的第三行Q?/p>
typedef (int*) pINT;
以及下面q行:
#define pINT2 int*
效果相同Q实则不同!实践中见差别QpINT a,b;的效果同int *a; int *b;表示定义了两个整型指针变量。而pINT2 a,b;的效果同int *a, b;
表示定义了一个整型指针变量a和整型变量b?/p>
注意Q两者还有一个行?L区别哦!
Origin:http://www.zhmy.com/blog2006004/goto723/archives/2006/29705.shtml
?/font>Q就是那些由~译器在需要的时候分配,在不需要的时候自动清除的变量的存储区。里面的变量通常是局部变量、函数参数等?
?/font>Q就是那些由new分配的内存块Q它们的释放~译器不,而是q序员自己LӞ一般一个newp对应一个delete。如果程序员没有释放掉,那么在程序结束后Q操作系l会自动回收?
自由存储?/font>Q就是那些由malloc{分配的内存块,它和堆是十分怼的,不过它是用free来结束自q生命的?
全局/静态存储区Q全局变量和静态变量被分配到同一块内存中Q在以前的C语言中,全局变量又分为初始化的和未初始化的,在C++里面没有q个区分了,他们共同占用同一块内存区?
帔R存储?/strong>Q这是一块比较特D的存储区,它们里面存放的是帔RQ不允许修改Q当Ӟ你要通过非正当手D也可以修改Q而且Ҏ(gu)很多Q在《const的思考》一文中Q我l出?U方法)
明确区分堆与?/font>
在bbs上,堆与栈的区分问题Q似乎是一个永恒的话题Q由此可见,初学者对此往往是淆不清的Q所以我军_拿它W一个开刀?
首先Q我们D一个例子:
void f() {
int* p=new int[5];
}
q条短短的一句话包含了堆与栈,看到newQ我们首先就应该惛_Q我们分配了一块堆内存Q那么指针p呢?它分配的是一块栈内存Q所以这句话的意思就是:在栈内存中存放了一个指向一块堆内存的指针p?/span>
在程序会先确定在堆中分配内存的大,然后调用operator new分配内存Q然后返回这块内存的首地址Q放入栈中,他在VC6下的汇编代码如下Q?
00401028 push 14h
0040102A call operator new (00401060)
0040102F add esp,4
00401032 mov dword ptr [ebp-8],eax
00401035 mov eax,dword ptr [ebp-8]
00401038 mov dword ptr [ebp-4],eax
q里Q我们ؓ了简单ƈ没有释放内存Q那么该怎么去释攑֑Q是delete p么?错了Q应该是delete []pQ这是ؓ了告诉编译器Q我删除的是一个数l,VC6׃Ҏ(gu)相应的Cookie信息去进行释攑ֆ存的工作?
好了Q我们回到我们的主题Q堆和栈I竟有什么区别?
主要的区别由以下几点Q?
1、管理方式不同;
2、空间大不同;
3、能否生碎片不同;
4、生长方向不同;
5、分配方式不同;
6、分配效率不同;
理方式Q对于栈来讲Q是q译器自动理Q无需我们手工控制Q对于堆来说Q释攑ַ作由E序员控ӞҎ(gu)产生memory leak?
I间大小Q一般来讲在32位系l下Q堆内存可以辑ֈ4G的空_从这个角度来看堆内存几乎是没有什么限制的。但是对于栈来讲Q一般都是有一定的I间大小的,例如Q在VC6下面Q默认的栈空间大是1MQ好像是Q记不清楚了Q。当Ӟ我们可以修改Q?
打开工程Q依ơ操作菜单如下:Project->Setting->LinkQ在Category 中选中OutputQ然后在Reserve中设定堆栈的最大值和commit?
注意QReserve最gؓ4ByteQcommit是保留在虚拟内存的页文g里面Q它讄的较大会使栈开辟较大的|可能增加内存的开销和启动时间?
片问题Q对于堆来讲Q频J的new/delete势必会造成内存I间的不q箋Q从而造成大量的碎片,使程序效率降低。对于栈来讲Q则不会存在q个问题Q因为栈是先q后出的队列Q他们是如此的一一对应Q以至于永远都不可能有一个内存块从栈中间弹出Q在它弹Z前,在它上面的后q的栈内容已l被弹出Q详l的可以参考数据结构,q里我们׃再一一讨论了?
生长方向Q?font style="BACKGROUND-COLOR: #33cccc">对于堆来Ԍ生长方向是向上的Q也是向着内存地址增加的方向;对于栈来Ԍ它的生长方向是向下的Q是向着内存地址减小的方向增ѝ?/font>
分配方式Q堆都是动态分配的Q没有静态分配的堆。栈?U分配方式:静态分配和动态分配。静态分配是~译器完成的Q比如局部变量的分配。动态分配由alloca函数q行分配Q但是栈的动态分配和堆是不同的,它的动态分配是q译器q行释放Q不需要我们手工实现?
分配效率Q栈是机器系l提供的数据l构Q计机会在底层Ҏ(gu)提供支持Q分配专门的寄存器存放栈的地址Q压栈出栈都有专门的指o执行Q这决定了栈的效率比较?我的注释:关于EBP寄存器请参考另一文?/font>)?/span>
堆则是C/C++函数库提供的Q它的机制是很复杂的Q例如ؓ了分配一块内存,库函C按照一定的法Q具体的法可以参考数据结?操作pȝQ在堆内存中搜烦可用的够大的I间Q如果没有够大的I间Q可能是׃内存片太多Q,有可能调用pȝ功能d加程序数据段的内存空_q样有Z分到_大小的内存,然后q行q回。显Ӟ堆的效率比栈要低得多?br>
从这里我们可以看刎ͼ堆和栈相比,׃大量new/delete的用,Ҏ(gu)造成大量的内存碎片;׃没有专门的系l支持,效率很低Q由于可能引发用h和核心态的切换Q内存的甌Q代价变得更加昂c所以栈在程序中是应用最q泛的,q是函数的调用也利用栈d成,函数调用q程中的参数Q返回地址QEBP和局部变量都采用栈的方式存放。所以,我们推荐大家量用栈Q而不是用堆?
虽然栈有如此众多的好处,但是׃和堆相比不是那么灉|Q有时候分配大量的内存I间Q还是用堆好一些?
无论是堆q是栈,都要防止界现象的发生(除非你是故意使其界Q,因ؓ界的结果要么是E序崩溃Q要么是摧毁E序的堆、栈l构Q生意想不到的l果,q是在你的E序q行q程中,没有发生上面的问题,你还是要心Q说不定什么时候就崩掉Q那时候debug可是相当困难的:Q?nbsp;
FILE * fopen(char *filename, char *openmode) 打开文g
int fclose(FILE * fp) 关闭文g
int fseek(FILE *fp, long offset, int base) 文g定位
void rewind(FILE *fp) 文g指针回到文g?/p>
long ftell(FILE *fp) q回fp所指文件读写位|?/p>
int fgetc(FILE *fp) 从fp所指文件读1个char
char * fgets(char *buffer, int n, FILE *fp) 从fp所指文件读n个char
int fputc(char ch, FILE *fp) 向fp所指文件写1个char
int fputs(char * str, FILE *fp) 向fp所指文件写n个char
int fread(char *buffer, int size, int n, FILE *fp) 从fp所指文件读n个size到buffer
int fwrite(char *str, int size , int n, FILE *fp) 把str指向的n*size char写到文g
int fscanf(FILE *fp, char *format, args......) 从fp所指文件按format格式数据读到args所指的内存单元?
int fprintf(FILE *fp, char *format, args......) 把args的值按format所指的格式写到fp所指的文g?/p>
int feof(FILE *fp) 查文件是否结? l束反回非0?/p>
int ferror(FILE *fp) 查文件是否出?没有出错时反?
void clearerr(FILE *fp) 使fp所指的文g的错?标志和文件结束等|?br>