讀書筆記(二)

2021-07-09 03:01:26 字數 4362 閱讀 7739

使用數學函式的時候,大多數需要包含標頭檔案,但是也有特例,例如處理整型數的函式abs函式被包含在標頭檔案中

三角函式和反三角函式,都以弧度為引數,而不是以角度為引數。

更加詳細的數學函式可以參考c mathematical functions。-維基百科

strcpy、strcat函式會改變傳入的字串的內容。程式設計師需要確保傳入的位址有足夠的空間容納改變後的字串。也就是說strcpy、strcat函式對傳入的空間不做容量檢查。一不小心就是發生溢位。

為了解決字串函式的溢位問題,引進了strncpy、strncat兩個函式。例如有如下例子:

#include

int main()

; char des[10]=;

strncat(des,str);

}

利用strncat函式,我們可以呼叫strncat函式strncat(des,str,4)這一語句,這個函式從str中取出前4個字元鏈結到des的後邊,des字串成為」hellowor」,最後還有乙個』\0』作為字串結尾。

乙個中心,兩個基本點

乙個中心:time_t time(time_t *timer)函式

兩個基本點:系統時間time_t( 從1970.1.1日0時0分0秒到當前一刻所經過的秒數)和日曆時間struct tm 。(分別表示的年月日時分秒等)

時間函式演示程式:

#include

#include

int main()

利用時間函式設定隨機數種子,srand(time(null))例,產生100個0到1之間的隨機數的程式:

int main()

}

熟悉標準函式庫中的函式。

參考:the c library reference guide

對於陣列int array[3],有

1. 陣列變數array即是此陣列的首位址。其與&array[0]等價。同時array的位址不能改變。

2. 陣列的下標從0開始。

3. 定義陣列的時候,編譯器會根據陣列的長度宣告一塊連續記憶體的位址給陣列。

4. 陣列定義的時候,必須指定其長度

int

array[3];

/*初始化例1*/

for(int i=0;i<3;i++)

/*初始化例2,對乙個陣列中的所有元素都置為0*/

memset(array,0,sizeof(array));

一般來說,陣列的賦值以及初始化使用迴圈操作:

int a[3]=,b[3];

b=a;/*錯誤,不能把陣列名放到等號左邊。*/

//陣列間賦值之迴圈方法

for(int i=0;i<3;i++)

//陣列間賦值高效方法

memcpy(b,a,sizeof(a));//注意sizeof的用法

vs中的每一乙個專案,都可以分別建立debug版和release版,release版通常不進行邊界檢查,這是與debug版之間最大的區別之一。

debug版下,當定義一塊陣列的時候,它會在陣列的後面加上兩個元素,如下圖所示。一旦由於陣列越界而操作了陣列後面加上的這兩個元素,程式將會終止,同時系統彈出乙個對話方塊,來提示陣列發生了越界。

當定義乙個指標的時候如果不對他進行初始化,那麼它指向的就是乙個不確定的值,這種情況下,當我們訪問該指標指向的變數時,程式可能就會發生問題。

野指標的解決辦法:

如果不知道指標暫時指向何方,那就讓他暫時指向null。

即:short *ptr=null

指標賦值的幾種形式:

int *p1,*p2;

int a=10;

intarray=;

p2=&array[2];

p1=&a;

p1=array;

p1=(int *)malloc(sizeof(int));//強制轉換malloc申請的記憶體。

p1=null;//p1指向空指標

void的一種用法是宣告乙個void型別的指標,void *vp;對於void型別的指標,其只儲存乙個位址,而不包含變數的型別資訊,所以任何型別的指標都可以直接賦值給他而無需進行強制轉換。

由於void型別指標只包含位址資訊,不包含長度資訊,將任何型別的指標賦值給void型別指標時都會丟失長度資訊。所以對void型別指標進行算術運算和進行取值操作都是不允許的。

如果指標p指向陣列變數a,則通過陣列下標訪問陣列中的元素和通過指標加偏移量來訪問陣列中的元素是等價的。

當a[i]用在乙個表示式中的時候 ,編譯器會自動將其轉換成為指標加偏移量*(a+i)的形式,所以a[i]這種書寫方式只是為了給程式設計師書寫**的時候準備的。經過編譯之後是不存在a[i]這種形式的。

當陣列型別被用於宣告函式形參的時候,如申明函式func(int a),編譯器會將其自動轉換為func(int *a);

指標和陣列的不同:

1. 不能改變陣列變數a的位址,所以a++這種寫法是不行的。但是指向陣列的指標變數pa卻可以寫成pa++是沒有問題的。因為指標可以改變指向。

2. 當指標pa指向乙個單獨的變數時,指標的行為和陣列就沒有相同之處了。

3. 如果在乙個檔案中定義成 int a[5],而在另外乙個包含的檔案中使用extern int *a這樣的卻是不允許的。

malloc函式和colloc函式的區別

1. 引數不同:

void *malloc(size_t size);

void *calloc(size_t numelements,size_t sizeofelement);

真正的不同是這兩個函式申請記憶體完成後的動作。calloc會將分配的記憶體中的每一位都初始化為零。

兩個函式分配的時候都是以位元組為單位。例如像分配10個int型的數,則應該寫成malloc(sizeof(int)*10).

返回值是void型別,因此需要把其轉換成需要的型別,例如

int p=(int )malloc(sizeof(int)*10).

這兩個函式的使用均應該包含標頭檔案

memcpy與memmove的目的都是將n個位元組的源記憶體位址的內容拷貝到目標記憶體位址中。

但當源記憶體和目標記憶體存在重疊時,memcpy會出現錯誤,而memmove能正確地實施拷貝,但這也增加了一點點開銷。

memmove用於從src拷貝count個字元到dest,如果目標區域和源區域有重疊的話,memmove能夠保證源串在被覆蓋之前將重疊區域的位元組拷貝到目標區域中。但複製後src內容會被更改。但是當目標區域與源區域沒有重疊則和memcpy函式功能相同。

乙個關於陣列指標的例子

main()

;int

*ptr=(int

*)(&a+1);

printf("%d,%d",*(a+1),*(ptr-1));

}

列印出來是:2 5分析:

對乙個指標加1操作,得到的是下乙個元素的位址,而不是原有位址的值直接加1.所以,乙個型別為t的指標的移動,以sizeof(t)為移動單位。

因此對上例來說,a是乙個一位陣列,陣列中有5個元素,所以a的型別是陣列指標。

ptr是乙個指向int型的指標,所以ptr是整型指標。

&a+1:取陣列a的首位址,該位址的值加上sizeof(a)的值,即為&a+5*sizeof(int),即下乙個陣列的首位址。 (int )(&a+1): 則是把上一步計算出來的位址,強制轉換為int 型別,賦值給ptr。

*(a+1): a,&a的值是一樣的,但意思不一樣,a是陣列首元素的首位址,也就是a[0]的首位址,&a是陣列的首位址,a+1是陣列下一元素的首位址,即a[1]的首位址,&a+1是下乙個陣列的首位址。

下面程式段包含4個函式,其中具有隱含this指標的是()

int

f1();

class

t;

正確答案: d 你的答案: a (錯誤)

f1 f2

f3 f4

答案分析:類的每個非靜態成員函式都含有乙個指向當前物件的指標,即this指標。

讀書筆記二

複審 即看 是否在 規範 的框架內正確地解決了問題。形式有 自我複審 同伴複審 團隊複審。目的是 1 找出 錯誤 2 發現邏輯錯誤 3 發現演算法錯誤 4 發現潛在的錯誤和回歸性錯誤 5 發現可能需要改進的地方 6 教育 互相教育 開發人員,傳授經驗,讓更多的成員熟悉專案各部分的 同時熟悉和應用領域...

Effective Java讀書筆記二

我們在設計類的時候,有些類難免會有許多的字段 fields 而這些字段可能需要在建立物件的時候對它們進行賦值。一般我們會考慮兩種方式 使用建構函式或者使用setter方法。使用建構函式的缺點很明顯,如果我們的字段過多,那麼就會讓建構函式的引數過多,在這種情況下,不但不容易理解和閱讀,而且非常容易出錯...

C Primer讀書筆記(二

關於delete一些注意點 在delete之後,最好要重設指標的值,舉例 delete p 執行之後 p變成了沒有定義,在很多機器上,儘管p沒有意義,但是仍然存放它之前所指向物件的位址,然後p所指向的記憶體已經被釋放,因為p不在有效。刪除指標之後,該指標變成懸垂指標,懸垂指標指向曾經存放的記憶體,但...