1. 程式人生 > >C語言理論知識-生存期

C語言理論知識-生存期

各種基本型別的位元組數

void main()
{
	cout << sizeof(char) << endl;
	cout << sizeof(short) << endl;
	cout << sizeof(int) << endl;
	cout << sizeof(long int) << endl;
	cout << sizeof(long long) << endl;
	cout << sizeof(float) << endl;
cout << sizeof(double) << endl; cout << sizeof(long double) << endl; cout<<endl;/////////////////////////////// cout << sizeof(char*) << endl; cout << sizeof(short*) << endl; cout << sizeof(int*) << endl; cout << sizeof(long int*) << endl; cout <<
sizeof(long long*) << endl; cout << sizeof(float*) << endl; cout << sizeof(double*) << endl; cout << sizeof(long double*) << endl;//在當前系統之下 指標為4位元組; }

生存期:是指編譯通過後的情況

int *fun()
{
	int x = 10;
	return &x;
}
void add()
{

}
void main()
{
	int *p = NULL
; p = fun(); //add(); cout << *p << endl; }

當加上呼叫add()時得出的結果是一個隨機值
在這裡插入圖片描述
而不呼叫add()時則可以得到結果10
在這裡插入圖片描述
在不呼叫add時,雖然fun()函式在執行完之後空間會被釋放,但是在這時候沒有干擾到這一塊的空間,所以p=fun()依舊指向了x的值。然而當呼叫add時,棧幀的呼叫時連續的,比如main時一樓的棧幀,fun時二樓的棧幀,當fun()執行完後釋放,又把fun的棧幀空間給了add(),同時在給add()時會將fun釋放後的空間打掃一邊會用16進位制數0xcccccccc來填充。所以同時p=fun()就失效了,這是p就變成了失效指標。只要fun()被釋放不管p能不能得到x的值都是失效指標。但是當printf()輸出一個數組時輸出的數可能不是全0xcccccccc應為printf()這個函式也會侵佔上一個函式的棧幀,但是他不一定會影響上一個函式的值。如果一直測試都是那個值只能說明是運氣問題總之下面這樣的程式是據不允許的
在這裡插入圖片描述
但是

int fun()
{
	int x = 100;
	return x;
}
void mian()
{
	int a = fun();
}

這樣的程式是允許的應為return的x是一個臨時量是放在cpu的暫存器中的
另外全域性變數是存放在資料區的

char *str = "yhping"
void main()
{
	char *ch = "hellow";

}

在上面的的程式中str是全域性變數在資料區ch是區域性變數在棧區,而hellow和yhping是常量在資料區,全域性變數還有靜態變數也在資料區
靜態變數在第一次呼叫時初始化被產生而且初始化一次,它的生存期是從產生開始一直到程式的結束

int *fun(int x)
{
	static int a = x;//靜態變數只在執行時初始化一次,所以後來的x也沒有是a再次初始化。存放於資料區,將a的空間分配於資料區
	                     之所以之初始化一次,是應為在第一次初始化其時,在他的空間處設計了一個標記域,在未初始化之前比如標記域的值為0;
						 而初始化之後把他改為1,這樣在第二次初始化時檢查到標記域的值為1,這樣就進行第二次初始化

	static int b = 0;//b是一個常量在編譯時就會完成,在資料區開闢空間存放數
	++a;
	cout << a;
	return &a;
}
void main()
{
	int *p = NULL;
	for (int i = 10; i > 0; --i)
	{
		p = fun(i);//之所以可以這樣做是應為靜態變數即使在fun()函式被釋放後依然存在於資料區,所以可以執行
		*p += 100;//這樣是會改變靜態變數a的值的
	}

}

正是應為靜態變數的這種特性,所以為了返回陣列時,可以把陣列定義為靜態變數,就可已返回陣列的值,但是這樣的方式有侷限性,所以當需要返回多個型別不同的值時建議使用結構體進行返回

struct student
{
	char id[10];
	char name[10];
	char sex;
	int age;
};
student *fun()
{
	student s = { "20180101", "yhping", 'm', 28 };
	return &s;
}
void main()
{
	student *sp = fun();
	cout <<sp->age;
}

這樣雖然可能得到結果,這是應為沒有被別的函式在獲取記憶體空間是沒有被替代,但是這樣做是不合法的,可能會造成錯誤,這就是函式的生存期問題。所以最好把整個結構體返回

但是有一個例外就是malloc開闢的堆記憶體空間

int *getarray(int n)//不再生存期問題中,函式空間在棧中,malloc在堆中,雖然函式死亡,但是堆空間開闢的記憶體空間依舊存在
{
	int *s = (int *)malloc(sizeof(int)*n);
	return s;     //所以s在main中依舊能夠在主函式中呼叫
}

void main()
{
	int n;
	cin >> n;
	int *p = getarray(n);
	for (int i = 0; i < n; i++)
		p[i] = i;
	for (int i = 0; i < n; i++)
		cout << p[i] << endl;
	free(p);
	p = NULL;
}