C C 學習筆記 基礎知識7

2021-06-23 08:48:19 字數 4702 閱讀 8244

1字元和字串

在 c 語言中字元用它們的字符集值對應的小整數表示。因此, 你不需要任何轉換函式: 如有你有字元, 你就有它的值。

數字字元和它們對應的 0-9 的數字之間相互轉換時, 加上或減去常數 』0』, 也就是說, 』0』 的字元值。

字串用字元陣列表示; 通常你操作的是字元陣列的第乙個字元的指標,c語言從來不會把陣列作為乙個整體操作 (賦值, 比較等)。

strcat(string, "!");    //正確

strcat(string, '!'); //錯誤, strcat() 用於連線字串

if(string == "value") //錯誤

//上面**段中的 == 操作符比較的是兩個指標 —— 指標變數 string 的值和字串常數 「value」 的指標值 —— 看它們是否相等,

//也就是說, 看它們是否指向同乙個位置。它們可能並不相等, 所以比較決不會成功。

// 較兩個字串, 一般使用庫函式 strcmp():

if(strcmp(string, "value") == 0)

char a = "hello, world!";

char b[14];

b = "hello, world!"; //錯誤,字串是陣列, 而你不能直接用陣列賦值。

strcpy(b, "hello, world!"); //正確,使用 strcpy() 代替

cout << sizeof("a") << endl; //2,"a" 是字串

cout << sizeof('a') << endl; //1, 'a' 是字元

char r = 'abc';

cout << sizeof(r) << endl; //1, ???

cout << sizeof('abc') << endl; //4, ???

2布林表示式和變數

c 語言沒有提供標準的布林型別,可以使用以下任何一種形式。

#define true 1 

#define false 0

#define yes 1

#define no 0

enum bool ; //預設地,第乙個列舉成員賦值為0,後面的每個列舉成員賦的值比前面的大1

enum bool ;

//或直接使用 1 和 0 , 只要在同一程式或專案中一致即可。

//如果你的偵錯程式在檢視變數的時候能夠顯示列舉常量的名字, 可能使用列舉更好。

//有些人更喜歡這樣的定義

#define true (1==1)

#define false (!true)

//或者定義這樣的 「輔助」 巨集

#define istrue(e) ((e) != 0)

c 語言中的確任何非零值都都被看作真, 但這僅限於 「輸入」, 也就是說, 僅限於需要布林值的地方。內建操作符生成布林值時, 可以保證為 1 或 0。

一般規則是只在向布林變數賦值或函式引數中才使用 true 和 false (或類似的東西), 或者用於函式的返回值,但決不用於比較

預處理巨集 true 和 false (當然還有 null) 只是用於增加**可讀性, 而不是因為其值可能改變

儘管使用 true 和 false 這樣的巨集 (或者 yes 和 no) 看上去更清楚, 布林值和定義在 c 語言中的複雜性讓很多程式設計師覺得 true 和 false 巨集不過更令人迷惑, 因而更喜歡使用 1 和 0

3標頭檔案

(1)程式分成多個原始檔, 把什麼放到 .c 檔案, 把什麼放到 .h 檔案

作為一般規則, 把如下東西放入頭 (.h) 檔案中:

· 巨集定義 (預處理 #defines)

· 結構、聯合和列舉宣告

· typedef 宣告

· 外部函式宣告

· 全域性變數宣告

當宣告或定義需要在多個檔案中共享時, 尤其需要把它們放入標頭檔案中。特別是, 永遠不要把外部函式原型放到 .c 檔案中。

另一方面, 如果定義或宣告為乙個 .c 檔案私有, 則最好留在 .c 檔案中。

(2)標頭檔案定義技巧是:

#ifndef hfilename_used

#define hfilename_used

//... 標頭檔案內容 ...

#endif

每乙個標頭檔案都使用了乙個獨一無二的巨集名。這令標頭檔案可自我識別,以便可以安全的多次包含; 而自動 makefile 維護工具可以很容易的處理巢狀包含檔案的依賴問題

(3 )  #include <>  語法通常用於標準或系統提供的標頭檔案, 而 #include ""  通常用於程式自己的標頭檔案。

用 <> 括起來的標頭檔案會先在乙個或多個標準位置搜尋。用 "" 括起來的標頭檔案會首先在 「當前目錄」 中搜尋, 然後 (如果沒有找到) 再在標準位置搜尋。

(4) 根據 「缺少的」 標頭檔案的種類, 有幾種情況。

如果缺少的標頭檔案是標準標頭檔案, 那麼你的編譯器有問題。你得向你的供貨商或者精通你的編譯器的人求助。

對於非標準的標頭檔案問題更複雜一些。有些完全是系統或編譯器相關的。某些是完全沒有必要的, 而且應該用它們的標準等價物代替。例如, 用 代替 。其它的標頭檔案, 如跟流行的附加庫相關的, 可能有相當的可移植性。

標準標頭檔案存在的部分原因就是提供適合你的編譯器, 作業系統和處理器的定義。你不能從別人那裡隨便拷貝乙份就指望它能工作, 除非別人跟你使用的是同樣的環境.

(5  )引數個數可變的巨集

用乙個單獨的用括弧括起來的的 「引數」 定義和呼叫巨集, 引數在巨集擴充套件的時候成為類似 printf() 那樣的函式的整個引數列表。

#define debug(args) (printf("debug: "), printf args)

if(n != 0) debug(("n is %d\n", n));

//明顯的缺陷是呼叫者必須記住使用一對額外的括弧。

#if 預處理指令只處理整數

#pragam 指令提供了一種單一的明確定義的 「救生艙」, 

可以用作各種 (不可移植的) 實現相關的控制和擴充套件: 原始碼表控制、結構壓縮、警告去除 (就像 lint 的老 /* notreached */ 注釋), 等等

#pragma once  某些預處理器實現的擴充套件用於使標頭檔案自我識別

4輸入輸出

scanf("%d", i); //錯誤,傳給 scanf() 的引數必須是指標。

scanf("%d", &i) // 正確

char s[30]; scanf("%s", s);

// 不用 & 也可以。需要指標; 並不表示一定需要 & 操作符。

// 當你向 scanf() 傳入乙個指標的時候, 你不需要使用 &, 因為不論是否帶 & 操作符, 陣列總是以指標形式傳入函式

在 scanf() 轉換數字的時候, 它遇到的任何非數字字元都會終止轉換並被保留, 除非採用了其它的步驟, 那麼未預料到的非數字輸入會不斷「阻塞」 scanf():

scanf() 永遠都不能越過錯誤的非數字字元而處理後邊的合法數字字元。如果使用者在數字格式的 scanf 如 %d 或 %f 中輸入字元 『x』, 那麼提示後並用同樣的 scanf() 呼叫重試的**會立即遇到同乙個 』x』。

用 scanf %d 讀取乙個數字, 然後再用 gets() 讀取字串, 但是編譯器好像跳過了 gets() 呼叫?

scanf %d 不處理結尾的換行符。如果輸入的數字後邊緊接著乙個換行符, 則換行符會被 gets() 處理。

作為一般規則, 你不能混用 scanf() 和 gets(), 或任何其它的輸入例程的呼叫; scanf 對換行符的特殊處理幾乎一定會帶來問題。要麼就用 scanf() 處理所有的輸入, 要麼乾脆不用

在 printf 的格式串中輸出乙個 』%』

只需要重複百分號: %%,而 \%不行, 因為反斜槓 \是編譯器的轉義字元, 而這裡我們的問題最終是 printf 的轉義字元

讀取二進位制資料檔案的時候你應該用 「rb」 呼叫 fopen(), 確保不會發生文字檔案的解釋。類似的, 寫二進位制檔案時, 使用 「wb」。

注意文字/二進位制區別只是發生在檔案開啟時: 一旦檔案開啟之後, 在其上呼叫何種 i/o 函式無關緊要。

同時向兩個地方輸出, 如同時輸出到螢幕和檔案?

直接做不到這點。但是你可以寫出你自己的 printf 變體, 把所有的內容都輸出兩次。下邊有個簡單的例子:

#include #include void f2printf(file *fp1, file *fp2, char *fmt, ...)

//這裡的 f2printf() 就跟 fprintf() 一樣, 除了它接受兩個檔案指標並同時輸出到兩個檔案

5 產生標準分布或高斯分布的隨機數?

#include #include double gaussrand()

while(s >= 1 || s == 0);

x = v1 * sqrt(-2 * log(s) / s);

} else

phase = 1 - phase;

return x;

}

C C 學習筆記 基礎知識3

1 和 和 有什麼區別 1 和 對運算元進行求值運算,和 只是判斷邏輯關係。2 和 在在判斷左側運算元就能確定結果的情況下就不再對右側運算元求值。注意 在程式設計的時候有些時候將 或 替換成 或 沒有出錯,但是其邏輯是錯誤的,可能會導致不可預想的後果 比如當兩個運算元乙個是 1 另乙個是 2 時 2...

C C 學習筆記 基礎知識6

1複雜表示式與序列點 序列點是乙個時間點 在整個表示式全部計算完畢之後或在 或逗號運算子處,或在函式呼叫之前 此刻塵埃落定,所有的 都已確保結束.ansi iso c 標準這樣描述 在上乙個和下乙個序列點之間,乙個物件所儲存的值至多只能被表示式的計算修改一次。而且前乙個值只能用於決定將要儲存的值。i...

C C 學習筆記 基礎知識10

1棧 堆和靜態區 一般來說,可以簡單的理解為記憶體分為三個部分 靜態區,棧,堆。其實堆疊就是棧,而不是堆。堆的英文是heap 棧的英文是stack,也翻譯為堆疊。堆和棧都有自己的特性。記憶體也是這樣,記憶體的三個部分,不是所有的東西都能存進去的。靜態區 儲存自動全域性變數和static變數 包括st...