筆記 C語言 函式與程式結構

2021-09-18 06:04:32 字數 3727 閱讀 8941

函式的定義形式如下:

返回值型別 函式明(引數宣告表)

函式定義中的各構成部分都可以省略。最簡單的函式如下所示:

dummy() {}

該函式不執行任何操作也不返回任何值。這種不執行任何操作的函式有時很有用,它可以在 程式開發期間用以保留位置(留待以後填充**)。如果函式定義中省略了返回值型別,則默 認為 int 型別。

c 語言不允許在乙個函式中定義其它函式

函式的宣告與定義必須一致,否則結果會失去意義(資料型別會不一致會造成資料丟失)

c語言程式可以看成由一系列的外部物件構成,這些外部物件可能是變數或函式。

預設情況下,外部變數與函式具有下列性質:通過同乙個名字對 外部變數的所有引用(即使這種引用來自於單獨編譯的不同函式)實際上都是引用同乙個對 象(標準中把這一性質稱為外部鏈結)

如果函式之間要共享大量的變數,使用外部變數比使用很長的引數列表要高效方便的多。

缺點:對程式結構造成不良影響、導致程式中各個函式之間具有太多的資料聯絡。

外部變數的用途還表現在它們與內部變數相比具有更大的作用域和更長的生存期。自動變數只能在函式內部使用,從其所在的函式被呼叫時變數開始存在,在函式退出時變數也將 消失。而外部變數是永久存在的,它們的值在一次函式呼叫到下一次函式呼叫之間保持不變。 因此,如果兩個函式必須共享某些資料,而這兩個函式互不呼叫對方,這種情況下最方便的 方式便是把這些共享資料定義為外部變數,而不是作為函式引數傳遞。

名字的作用域指的是可以使用改名字的部分。

在乙個源程式的所有原始檔中,乙個外部變數只能在某個檔案中定義一次,而其它檔案 可以通過 extern 宣告來訪問它(定義外部變數的原始檔中也可以包含對該外部變數的 extern 宣告)。外部變數的定義中必須指定陣列的長度,但 extern 宣告則不一定要指定數 組的長度。

extern(外部的)

外部變數的初始化只能出現在其定義中。

一方面是我們期望每個檔案只能訪問它完成任務所需 的資訊;另一方面是現實中維護較多的標頭檔案比較困難。我們可以得出這樣乙個結論:對於 某些中等規模的程式,最好只用乙個標頭檔案存放程式中各部分共享的物件。較大的程式需要 使用更多的標頭檔案,我們需要精心地組織它們。

主要還是看專案的大小,適當的選擇建立怎樣的標頭檔案,但是這些都只是為了 寫**和後期維護方便一些,編譯器編譯的結果可能不變

用 static 宣告限定外部變數與函式,可以將其後宣告的物件的作用域限定為被編譯原始檔的剩餘部分。

如果把函式宣告為 static 型別,則該函式名除了對該函式宣告所在的檔案可見外,其它檔案都無法訪問。

static 型別的內部變數同自動變數一樣,是某個特定 函式的區域性變數,只能在該函式中使用,但它與自動變數不同的是,不管其所在函式是否被 呼叫,它一直存在,而不像自動變數那樣,隨著所在函式的被呼叫和退出而存在和消失。換 句話說,static 型別的內部變數是一種只能在某個特定函式中使用但一直佔據儲存空間的變數。

register 宣告告訴編譯器,它所宣告的變數在程式中使用頻率較高。其思想是,將 register 變數放在機器的暫存器中,這樣可以使程式更小、執行速度更快。但編譯器可以 忽略此選項。

c 語言並不是 pascal 等語言意義上的程式塊結構的語言,它不允許在函式中定義函式。但 是,在函式中可以以程式塊結構的形式定義變數。變數的宣告(包括初始化)除了可以緊跟 在函式開始的花括號之後,還可以緊跟在任何其它標識復合語句開始的左花括號之後。以這 種方式宣告的變數可以隱藏程式塊外與之同名的變數,它們之間沒有任何關係,並在與左花 括號匹配的右花括號出現之前一直存在

沒怎麼明白什麼意思,就隨便試了一下,就是不停的輸出i的值,觀察i值的變化

#include#includevoid main() 

} else

printf("%d\n", i);

system("pause");

}

在不進行顯式初始化的情況下,外部變數和靜態變數都將被初始化為 0,而自動變數和寄 存器變數的初值則沒有定義(即初值為無用的資訊) 。

陣列的初始化可以在宣告的後面緊跟乙個初始化表示式列表,初始化表示式列表用花括 號括起來,各初始化表示式之間通過逗號分隔。

字元陣列的初始化比較特殊:可以用乙個字串來代替用花括號括起來並用逗號分隔的 初始化表示式序列。

c 語言中的函式可以遞迴呼叫,即函式可以直接或間接呼叫自身。

雖然就一句話但是是乙個非常好用的東西

檔案包含

檔案包含指令(即#include 指令)使得處理大量的#define 指令以及宣告更加方便。 在原始檔中,任何形如:

#include 「檔名」

或#include 《檔名》

的行都將被替換為由檔名指定的檔案的內容。如果檔名用引號引起來,則在原始檔所在 位置查詢該檔案;如果在該位置沒有找到檔案,或者如果檔名是用尖括號《與》括起來的, 則將根據相應的規則查詢該檔案,這個規則同具體的實現有關。被包含的檔案本身也可包含 #include 指令。

替換只對記號進行,對括在引號中的字串不起作用。例如,如果 yes 是乙個通過#define 指令定義過的名字,則在 printf(「yes」)或 yesman 中將不執行替換

可以通過#undef 指令取消名字的巨集定義,這樣做可以保證後續的呼叫是函式呼叫,而不 是巨集呼叫:

#undef getchar

int getchar(void)

形式引數不能用帶引號的字串替換。但是,如果在替換文字中,引數名以#作為字首則 結果將被擴充套件為由實際引數替換該引數的帶引號的字串(如果下面的例子看不懂就仔細閱讀這段話)。例如,可以將它與字串連線運 算結合起來編寫乙個除錯列印巨集:

#define dprint(expr) printf(#expr " = %g\n", expr)

使用語句

dprint(x/y)

呼叫該巨集時,該巨集將被擴充套件為:

printf("x/y" " = &g\n", x/y);

其中的字串被連線起來了,這樣,該巨集呼叫的效果等價於

printf("x/y = &g\n", x/y);

在實際引數中,每個雙引號"將被替換為",反斜槓\將被替換為\,因此替換後的字串是 合法的字串常量。

預處理器運算子##為巨集擴充套件提供了一種連線實際引數的手段。如果替換文字中的引數與 ##相鄰,則該引數將被實際引數替換,##與前後的空白符將被刪除,並對替換後的結果重新 掃瞄。例如,下面定義的巨集 paste 用於連線兩個引數

#define  paste(front, back)

front ## back

因此,巨集呼叫 paste(name, 1)的結果將建立記號 name1。

條件包含

#if語句對其中的常量整型表示式(其中不能包含 sizeof、型別轉換運算子或 enum 常 量)進行求值,若該表示式的值不等於 0,則包含其後的各行,直到遇到#endif、#elif 或 #else 語句為止(預處理器語句#elif 類似於 else if)。在#if 語句中可以使用表示式 defined(名字),該表示式的值遵循下列規則:當名字已經定義時,其值為 1;否則,其值 為 0。

這個真沒太看懂就不把例子放在這了

C語言《四》 函式與程式結構

如果函式定義中省略了返回值型別,則預設為int型別 返回值 如果某個函式從乙個地方返回時有返回值,而從另乙個地方返回時沒有返回值,該函式並不非法,但可能是一種出問題的徵兆。程式的載入 不同系統中,儲存多個原始檔中的c程式的編譯和載入機制是不同的,這裡看下unix系統,假設有三個函式分別存放在main...

C程式語言讀書筆記 函式與程式結構

1 函式把大的任務分解為小的任務,有很多小的任務不需要了解具體操作細節。2 如果函式定義中省略了返回值型別,則預設為int型別。程式可以看成是變數定義和函式定義的集合。函式之間的通訊可以通過引數,函式返回值以及外部變數進行,函式在原始檔 現的次序可以是任意的。只要保證每個函式不被分離到多個檔案中,源...

C語言程式結構

接下來就是逐條分析 1 在預處理指令中主要需要注意的是 include和 include stdio.h 是有區別的,籠統的說就是被包含與包含的關係。2 主函式注意定義型別,定義型別與最後的return對應,用於接收return的值 例如 include stdio.h int main 這裡的in...