[c 要點(diǎn)回顧]《C 程序設(shè)計新思維》 第6 - 8 章筆記
首先,這本書還是蠻值得一看的,然后呢,前六章是一些有用的工具的介紹。
第 6 章 玩轉(zhuǎn)指針
6. 1 自動,靜態(tài) 和手工內(nèi)存
C 提供三種內(nèi)存管理的模式,理解這三種概念,對于我們理解變量,尋找類似核心已轉(zhuǎn)移的bug有莫大的幫助。
自動
當(dāng)我們聲明一個變量后,當(dāng)程序離開他的作用域后,就會被程序銷毀
靜態(tài)
函數(shù)外部聲明的(文件作用域) 和 函數(shù)內(nèi)部使用static 聲明的都是靜態(tài)的,他們會在整個程序生命周期內(nèi)存在。且如果沒有初始化,默認(rèn)為0(NULL)
所以我們可以看出,靜態(tài)變量也是一種自動管理的模式,只不過作用域是文件作用域。
手動
即,malloc free ,也是唯一一種,在聲明之后改變數(shù)組長度的方式(使用 realloc() )
注意,這也是手動申請的數(shù)組無法使用sizeof來測量大小的原因
補(bǔ)充一下:
堆棧和棧:
任何函數(shù)都在內(nèi)存中占據(jù)一個空間,稱為函數(shù)幀,用以保存,與這個函數(shù)相關(guān)的信息,
例如,一個函數(shù)執(zhí)行后返回到哪里,以及保存所有自動分配的變量的空間
當(dāng)一個函數(shù)調(diào)用另一個函數(shù)的時候,第一個函數(shù)的函數(shù)幀中的活動就會暫停,并且一個心得函數(shù)被添加到這個函數(shù)幀中去,當(dāng)函數(shù)執(zhí)行完畢后,它的函數(shù)幀就會彈出,所有保存在這個函數(shù)幀的所有變量都會消失,這就是自動的變量管理的方式
注意的是這個堆棧的大小一般為2~3M 所以,當(dāng)需要更多的更加自由的管理方式的時候,我們就調(diào)用malloc ,從堆中要一塊內(nèi)存,歸自己管理,而這個堆就是內(nèi)存的大小。這也是及時使用free的重要性。
這是使用static 實(shí)現(xiàn)斐波那契數(shù)列的一個方式
/*************************************************************************
> File Name: staticTest.c
> Author:Gin.TaMa
> Mail:1137554811@qq.com
> Created Time: 2019年03月20日 星期三 14時42分53秒
************************************************************************/
#include<stdio.h>
long long int fib(){
static long long int first = 0;
static long long int second = 1;
long long int out = first + second;
first = second;
second = out;
return out;
}
int main(){
for(int i = 0;i < 10;i ++){
printf("%lld\n",fib());
}
return 0;
}
以及一個有意思的bug
/*************************************************************************
> File Name: staticBug.c
> Author:Gin.TaMa
> Mail:1137554811@qq.com
> Created Time: 2019年03月20日 星期三 14時46分40秒
************************************************************************/
#include<stdio.h>
char* aToA(char a){
static char A;
A = a + 'A' - 'a';
return &A;
}
void test(char* a){
printf("a = %c\n",*a);
// 沒有改變a的注意
char* b = aToA('b');
printf("a = %c ; b = %c\n",*a,*b);
// a的值改變了
}
int main(){
char* a = aToA('a');
printf("a = %c\n",*a);
test(a);
return 0;
}
猜一下結(jié)果是不是這樣的呢?
a = A
a = A
a = B ; b = B
這個bug一開始找了我半天。。
關(guān)鍵是我是調(diào)用別實(shí)現(xiàn)的aToA()這樣類似的函數(shù)。
這其實(shí)是叫做別名和賦值的區(qū)別
當(dāng)我們告訴計算機(jī)把a(bǔ)設(shè)置成b的時候有兩種意義
別名,賦值。
a 為 b的別名:意味著,修改a,就是在修改b。
a 為b的賦值: 意味著a與b僅是有相同的值,但是沒有半毛錢的關(guān)系。
這里就要注意了,
結(jié)構(gòu)被復(fù)制,數(shù)組創(chuàng)建別名
當(dāng)一個結(jié)構(gòu)體b里有一個數(shù)組的時候,
你想將b的值賦值給a,很有可能,a的數(shù)組是b的數(shù)組的別名,也就意味著,你修改了a的數(shù)組元素,就是在修改b的數(shù)組
* 的解釋
關(guān)于* 其實(shí)是一個不好的設(shè)計,它把兩種情況雜糅到了一起,需要你依據(jù)上下文判斷他的意思。
它違背了所謂的“功能截然不同的事務(wù),看上去應(yīng)該明顯不一樣”
注意 * 在聲明中,代表指針。在其他地方代表取指針指向的內(nèi)容。
所以
int* i = 3; // WRONG
int* i = malloc(sizeof(int)); // OK
*i = 3; // OK
記住這個就OK了。
第?。贰≌?,沒啥意思。
第8 章
8.1 營造健壯和繁榮的宏
==宏的本質(zhì)是一種沒有腦子的文本替換==
()括號,一定要加
{}也要加
-
避免重復(fù)作用
#define max(a,b) (((a) > (b)) ? (a) : (b))這個是有隱患的比如 max(i ++ ,x ) i 會被加兩次。。
補(bǔ)充
_VA_ARG_ 這是變參宏獲得變量的關(guān)鍵字
變參宏的一種用法。。
define printf_debug(format,...) printf(__FILE__"(%s:%d)"format"", __FUNCTION__, __LINE__, ##__VA_ARGS__)
8.3 const 關(guān)鍵字
注意 ==const 是一種文法,而不是一種鎖==
理解const的關(guān)鍵是從右向左閱讀,并且注意,const作用于const左邊的文本就像* 一樣。
int const = 一個(不變的)整數(shù)常量
int const * = 指向一個(不變的)整數(shù)常量的(可以變的)變量指針
int * const = 指向一個(可以變的)變量整數(shù) 的(不變的)常亮指針
注意 常量結(jié)構(gòu)的成員并不是常量。
OK 不。