您的位置:首页 > 编程语言 > C语言/C++

C语言内存四大区域几点总结

2017-07-26 19:58 113 查看


未初始化全局变量默认值为0,未初始化局部变量一般默认值为随机数,但有的编译器也为0。

一、栈:

  栈遵循后进先出,栈的大小由编译器决定。

一般来说,默认栈的大小为1M,所以如果变量分配内存过大可能会造成栈溢出。比如: 定义一个数组长度为200M,
double a[1024*1024*200]
如果编译器栈大小不够的话会造成溢出。

栈不同于堆,栈用完立即回收,所有局部变量都存放在栈中。

如下程序会一直进行分配与回收,该程序运行起来会很消耗CPU

while(1)
{
double  arr[1024*200];
}


计算机中计算是由CPU来完成的,而计算结果保存在内存中,所以a+1=2 这种赋值方式是错误的。

二、堆区:

内存分配函数有:malloc calloc realloc

分配的内存不会自动释放,需要配合free()使用。如果执行内存分配以后不释放,则会造成内存泄漏,严重的话会把内存分配完导致计算机崩溃。

用指针写for循环:

#include <stdio.h>
#include <stdlib.h>
void main()
{
int *p = (int *) malloc(sizeof(int)*10);
int num=0;
int *px=p;
for(;px<p+10;px++)
{
*px=num;
printf("%p\n,%d\n",px,*px);
num++;
}
}


注意:

指针本身是一个变量,他存放在栈区(&p)

指针所指向的地址存放在堆区(p)

三、代码段:

  存放函数的执行代码。例如:函数名(函数的入口地址),以及函数的参数。

常量位于代码区,代码区都是只读的。

1、函数指针的定义:

把函数名挖掉,用 (*p) 代替。

例如:void (*pfuc) ( 参数) =fuc; (fuc为函数名)

间接调用: pfuc(参数);

以上两个式子等价于:直接调用
fuc(参数)


2、关于const

#define N 10 宏定义有CPU产生,N不可取地址

const修饰的数据是一个伪常量(只读常量),只是限定编译器尽量不修改它修饰的变量,其实是可以间接修改的。

- const在前面

const int nValue;   //nValue是const

const char *pContent; //*pContent是const, pContent可变

const char* const pContent;  //pContent和*pContent都是const

const在后面,与上面的声明对等

int const nValue; //nValue是const

char const * pContent; //*pContent是const, pContent可变

char* const pContent; //pContent是const,*pContent可变

char const* const pContent; //pContent和*pContent都是const


const int num=10;
int data[10];      //不合法的,因为num是个伪常量(只读常量)


解析:常量是被编译器放在内存中的只读区域,当然也就不能够去修改它。而”只读变量”则是在内存中开辟一个地方来存放它的值,只不过这个值由编译器限定不允许被修改。C语言关键字const就是用来限定一个变量不允许被改变的修饰符(Qualifier)。上述代码中变量n被修饰为只读变量,可惜再怎么修饰也不是常量。而ANSI C规定数组定义时长度必须是”常量”,”只读变量”也是不可以的,”常量”不等于”不可变的变量”。但是在C++中,局部数组是可以使用变量作为其长度的。

间接修改const修饰数据的值:

所以可以用一个指针指向num,然后就可以通过指针来修改num的值了。

#include <stdio.h>
int main()
{
const int num=10;
int *p=(int *)#
*p=100;
printf("%d",num);
}


四、关于静态变量,局部变量,全局变量,外部变量:

对于局部变量:未初始化也叫定义,所以不能对一个变量申明两次。

对于全局变量:定义=申明+赋值。所以如果没有初始化只能叫做申明,所以可多次申明同一个变量,虽然没有什么意义。

静态变量和局部变量的区别:静态变量被限定在本C文件中才可以使用。

全局变量和外部变量,如下:

//test1.c
int a=2;

//test2.c
#include <stdio.h>
//int a;      函数体外部只需要申明即可以,但是不能给a赋值,否则就是重定义
void main()
{
extern int a;   //在函数体内部调用其他文件的全局变量,需要用extern申明
printf("%d",a);
}




参数入栈顺序:从左往右

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息