未初始化全局變量默認值爲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);
}
參數入棧順序:從左往右