1、堆和栈的区别
这里的堆和栈指的是内存里面的堆区和栈区。C语言的内存模型可以分为5类:栈区、堆区、静态区、常量区、代码区。
- 栈区stack:存放函数的参数值,局部变量等等。由编译器自动分配和释放(可以回忆编程的时候好像局部变量不需要特别的申请内存和释放),通常在函数执行结束之后释放。其操作方式类似于数据结构中的栈。栈内存分配运算一般都是内置于CPU指令集,可以理解为机器语言或者汇编语言,所以效率高。但是容量有限,IOS的栈区只有2M。
- 堆区heap:堆区是不连续的内存空间。一般通过new、malloc申请,通过delete、free释放,所以一般需要自己MRC(手动管理内存)。堆释放不当容易导致内存泄露。
- 静态区:全局变量和静态变量存储区。一般程序结束后,由系统释放。宏定义本质上就是字面值的替换,存储在静态区。
- 常量区:常量存储区域,不允许修改。比如字符串常量。
- 代码区:存放函数体的二进制代码
现在来看一下最基本的C语言程序:
#include <stdio>
#include <stdlib.h>
#define pi 3.1415926 //静态区
int sum(int i,int j);
int main(){
static int k=1; //静态区
int i=0,j=1; //栈
char *str="123"; //“123”在常量区,str在栈上
int *p=(int *)malloc(j*sizeof(int)); //申请堆
free(p); //释放堆
printf("%d",sum(i,j));
}
int sum(int i,int j){
int sum=i+j; //栈
return sum;
}
这是一个包含了上面五种存储区的典型C程序。其他的都在代码区。所以堆和栈的区别如下:
- 堆:需要手动动态申请和释放(MRC),可申请较大空间
- 栈:系统自动分配和释放,空间较小,一般只有1~2M。
2、引用与指针的区别
引用,相当于为对象起了一个别名,一般使用&d,d是引用变量的别名。
int i =1;
int &r = i; //r指向i(r是i的别名,可以通过操作r来改变i的值)、
r=2;
cout<<r<<" "<<i<<" "<<endl; //r和i的值都为2
int j=r; //j被初始化为i的值,即为2
引用需要注意以下问题:
- 引用可以当做对象用,但是不能像对象一样定义引用,即不能定义引用的引用
通俗的讲,为引用赋值,实际上就是将值赋给了与引用绑定的对象。获取引用的值,实际上就是获取了与引用绑定的对象的值。但是引用本身不是一个对象,所以不能定义引用的引用。 - 引用必须初始化
- 引用初始化完成,就和初始值对象绑定在一起,无法令引用重新绑定到新的对象
指针不用说了。
3、malloc()申请的内存空间能不能在函数中返回
是可以的,返回的是申请内存空间的首地址。实际上在C语言中,经常需要在函数中传入传出指针进行操作,这样可以对数组或者其他大量数据进行操作。同理,由于C语言的返回值只有一个,因此可以返回地址然后对地址进行操作。
4、概率函数调整
一个概率函数,返回0的概率是0.4,返回1的概率是0.6,写一个函数使得返回0的概率是0.4,返回1的概率是0.6。
思路及对应伪代码如下:
int fun(void){
}
// a=0,b=0 0.4*0.4
// a=1,b=0 0.6*0.4
// a=0,b=1 0.4 0.6
// a=1,b=1 0.6 0.6
int NewFun(void){
int flag=1;
while(flag){
a=fun();
b=fun();
if(a==0&&b==1))
flag=0;
return 0;
else if(a==1&&b==0))
flag=0;
return 1;
else
flag=1;
}
}