博文
[转载]内存区划分、内存分配、常量存储区、堆、栈、自由存储区、全局区(2008-05-15 01:00:00)
摘要:一. 在c中分为这几个存储区
1.栈 - 由编译器自动分配释放
2.堆 - 一般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收
3.全局区(静态区),全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。- 程序结束释放
4.另外还有一个专门放常量的地方。- 程序结束释放
&nbs......
[转贴]void及void指针深层探索(2008-05-13 13:14:00)
摘要:
void及void指针深层探索
1.概述
许多初学者对C/C++语言中的void及void指针类型不甚理解,因此在使用上出现了一些错误。本文将对void关键字的深刻含义进行解说,并详述void及void指针类型的使用方法与技巧。
2.void的含义
void的字面意思是“无类型”,void *则为“无类型指针”,void *可以指向任何类型的数据。
void几乎只有“注释”和限制程序的作用,因为从来没有人会定义一个void变量,让我们试着来定义:
void a;
这行语句编译时会出错,提示“illegal use of type 'void'”。不过,即使void a的编译不会出错,它也没有任何实际意义。
void真正发挥的作用在于:
(1) 对函数返回的限定;
(2) 对函数参数的限定。
我们将在第三节对以上二点进行具体说明。
众所周知,如果指针p1和p2的类型相同,那么我们可以直接在p1和p2间互相赋值;如果p1和p2指向不同的数据类型,则必须使用强制类型转换运算符把赋值运算符右边的指针类型转换为左边指针的类型。
例如:
float *p1;
int *p2;
p1 = p2;
其中p1 = p2语句会编译出错,提示“'=' : cannot convert from 'int *' to 'float *'”,必须改为:
p1 = (float *)p2;
而void *则不同,任何类型的指针都可以直接赋值给它,无需进行强制类型转换:
void *p1;
int *p2;
p1 = p2;
但这并不意味着,void *也可以无需强制类型转换地赋给其它类型的指针。因为“无类型”可以包容“有类型”,而“有类型”则不能包容“无类型”。道理很简单,我们可以说“男人和女人都是人”,但不能说“人是男人”或者“人是女人”。下面的语句编译出错:
void *p1;
int *p2;
p2 = p1;
提示“'=' : cannot convert from 'void *' to 'int *'”。 ......
[转贴]水滴石穿C语言之正确使用const(2008-05-13 13:13:00)
摘要:基本解释
const是一个C语言的关键字,它限定一个变量不允许被改变。使用const在一定程度上可以提高程序的健壮性,另外,在观看别人代码的时候,清晰理解const所起的作用,对理解对方的程序也有一些帮助。
虽然这听起来很简单,但实际上,const的使用也是c语言中一个比较微妙的地方,微妙在何处呢?请看下面几个问题。
问题:const变量 & 常量
为什么我象下面的例子一样用一个const变量来初始化数组,ANSI C的编译器会报告一个错误呢?
const int n = 5;
int a[n];
答案与分析:
1)、这个问题讨论的是“常量”与“只读变量”的区别。常量肯定是只读的,例如5, “abc”,等,肯定是只读的,因为程序中根本没有地方存放它的值,当然也就不能够去修改它。而“只读变量”则是在内存中开辟一个地方来存放它的值,只不过这个值由编译器限定不允许被修改。C语言关键字const就是用来限定一个变量不允许被改变的修饰符(Qualifier)。上述代码中变量n被修饰为只读变量,可惜再怎么修饰也不是常量。而ANSI C规定数组定义时维度必须是“常量”,“只读变量”也是不可以的。
2)、注意:在ANSI C中,这种写法是错误的,因为数组的大小应该是个常量,而const int n,n只是一个变量(常量 != 不可变的变量,但在标准C++中,这样定义的是一个常量,这种写法是对的),实际上,根据编译过程及内存分配来看,这种用法本来就应该是合理的,只是ANSI C对数组的规定限制了它。
3)、那么,在ANSI C 语言中用什么来定义常量呢?答案是enum类型和#define宏,这两个都可以用来定义常量。
来自:弘少 http://www.bansun.com/bbs/thread-4878-1-5.html......
做了一个选择、插入、冒泡与shell这四种排序的比较(2008-04-17 16:53:00)
摘要:#include <iostream>
#include <cstdlib>
#include <ctime>
inline void exch(int &A, int &B){int temp = A; A = B; B = temp;}
inline void compexch(int &A, int &B){if (A > B) exch(A,B);}
void selection_sort(int src[],int lengh);
void insertion_sort(int src[],int lengh);
void insertion_sort_adv(int src[],int lengh);
void bubble (int src[] , int lengh);
void quick_sort(int src[],int l, int lengh);
int partition(int src[],int l, int lengh);
void shell_sort(int src[], int lengh);
using namespace std;
int main()
{
int *src;
int index_i;
clock_t start, finish;
clock_t save[10];
int max;
cout <<"enter\n";
cin >>max;
src = (int *) malloc (max*sizeof(int));
for (index_i = 0; index_i < max ; index_i++)
src[index_i] =max - index_i;
start = clock();
selection_sort( src, max-1);
finish = ......
[转载][教程] C/C++指针简易教程(2008-03-19 11:10:00)
摘要:原帖请看:http://yzfy.org/bbs/viewthread.php?tid=710&extra=page%3D1
《对函数调用的深入探讨》:http://yzfy.org/bbs/viewthread.php?tid=688&extra=page%3D1
首先声明,这篇文章是给那些学完了指针,但是对指针的使用和实质还存在疑问的朋友。
如果你根本就没有学过指针,请先去参考一下几本经典的教材,再来看本文。
因为在这里将不会解释操作符的用法。
有人说,C的精髓在于指针,掌握指针的使用就掌握了C语言。当然这种说法不一定严谨,
但毕竟突出了指针的重要性,也导致了一些初学者“谈指针色变”,避指针唯恐不及,
生怕一不小心就用错导致莫名其妙的问题。那么指针是什么呢?指针的本质又是什么呢?
因为Q群里面很多人都在问相类似的问题,这里发一个指针的教程,希望对大家有帮助。
在讲指针之前,我们先说说类型转换。对类型转换完全了解的人可以跳过这一部分,
直接看指针,但是还是建议大家看看,说不定会对你有所帮助呢。
无论是C还是C++,类型转换都是比较难的。何谓类型转换?从一种类型转换位另一种类型是也!
C++是强类型语言,而C要宽松一些,所有的强类型语言都会有类型转换的操作,
因此看完这里大家就可以举一反三,对Java等等其他语言的类型转换有比较深的了解。
类型转换分为两种,一种是隐式类型转换,一种是显式类型转换。这里举一个例子:
int a=8.0/3;
.
8.0是double类型(C规定,程序中出现的任何无后缀小数都为double类型,
而出现的任何无后缀整数都为int型,在写程序时一定要记住),而3是int型。
除法运算可否在两种不同类型的变量之间进行呢?显然是不行的。因此,这里就需要转换。
我们知道,double型可表示的范围远远大于int型。而C和C++在这类转换中的原则就是,
范围小的类型向范围大的类型转换。所以,3被转换成了double值3.0,然后做除法。
8.0/3.0=......
为何数组名是指针常量(2008-03-16 12:09:00)
摘要:看了《C和指针》一书后了解到,当程序编译的时候, 数组的内存就已经分配好了,此时如果想要改变指针值,因为数组各元素的地址是连续的,那么就得将整个数组进行移动,因为数组名是指针常量,不能做左值。......
将getchar()获取的字符不赋任何变量时,这个字符它会被丢到哪(2008-03-16 12:01:00)
摘要:之前在书上看到,说是在调用有返回值的函数时其返回值会先放到寄存器中,然后再由寄存器来赋值给变量。于是我觉得,getchar()获取的字符不赋任何变量时,那么这个字符就不会赋值给任何变量,而且当再出现需要来调用该寄存器时,该寄存器中的值就会被顶掉。......
关于结构体中的"对齐"的目的(2008-03-16 11:44:00)
摘要:看汇编时发现了这么一句话:
"...同一个地址即可以看作字节单元的地址,又可以看成字单元、双字单元或4字单元的地址,这要根据使用情况确定。字单元的地址可以是偶数也可以是奇数。但是,在8086和80286中,访问存储器(要求取数或存数)都是以字为单位进行的,也就是说,机器是以偶地址访问存储器的,这样,对于奇地址的单元,要去一个字需要访问两次存储器,当然这样花费的时间多。在8086及其以后续的32位处理机中,双字节单元地址为4的整数倍数时访问存储器的速度可以较快.同样,4字单元的地址为8的倍数时访问速度更快..."
看了这句话后我就在想,结构体中的'对齐'是不是就是因为这个而产生的。后来多亏论坛上各路朋友的帮忙答疑,证实了我的看法,"对齐"目的确实是为了减少取指令次数,提升速度,代价是耗费较多的空间。
并且请他们的回帖中还了解到,结构体中的“对齐”其实是“补白”,而真正的对齐(alignment)其实是语言本身要求的,比如C/C++规定对齐很多时候处于类型转换等考虑的,具体情况请看C99和C++2003标准。这个对齐对于多数系统一般而言8字节足够。......