請問C語言怎麼把函式放在標頭檔案裡面呢

時間 2021-08-30 09:50:43

1樓:匿名使用者

一般的做法是,標頭檔案裡寫函式的宣告, 而實現寫在.c檔案裡

2樓:匿名使用者

你可以建立標頭檔案,標頭檔案是以".h"結尾的檔名,而main()函式所在的檔案則是以".c"結尾的,".

c"字尾的檔案內部,也就是main函式內部主要是呼叫各個功能函式,函式的宣告部分一般放在在".h"字尾的標頭檔案中,這樣是為了實現c語言的結構化,建立好了標頭檔案,就可以在標頭檔案內部實現各個函式的宣告,具體的一個完整的函式宣告可以用下面的加法函式例子來說明 :

//include,標頭檔案名為add的標頭檔案float add(float x,float y) /*定義add函式*/

這個函式的返回值是float(浮點型或是實型),add為函式名,呼叫的形參都是float型別,數目為兩個形參x,y。x,y是接受main()函式中的實參傳過來的具體值,然後進行運算。main函式呼叫只要這樣就可以:

#include

#include

main()

3樓:懶得上樓

如果編譯器支援 inline 修飾符的話

static inline void function(void)

c語言在標頭檔案中呼叫函式

4樓:韌勁

main()

例程-1

看看上面的程式,沒有.h檔案。是的,就是沒有,世界上的萬物都是經歷從沒有到有的過程的,我們對.

h的認識,我想也需要從這個步驟開始。這時確實不需要.h檔案,因為這個程式太簡單了,根本就不需要。

那麼如何才能需要呢?讓我們把這個程式變得稍微複雜些,請看下面這個,

檔名 first.c

printstr()

main()

例程-2

還是沒有, 那就讓我們把這個程式再稍微改動一下.

檔名 first.c

main()

printstr()

例程-3

等等,不就是改變了個順序嘛, 但結果確是十分不同的. 讓我們編譯一下例程-2

和例程-3,你會發現例程-3是編譯不過的.這時需要我們來認識一下另一個c語言中的概念:作用域.

我們在這裡只講述與.h檔案相關的頂層作用域, 頂層作用域就是從宣告點延伸到源程式文字結束, 就printstr()這個函式來說,他沒有單獨的宣告,只有定義,那麼就從他定義的行開始,到first.c檔案結束, 也就是說,在在例程-2的main()函式的引用點上,已經是他的作用域.

例程-3的main()函式的引用點上,還不是他的作用域,所以會編譯出錯. 這種情況怎麼辦呢? 有兩種方法 ,一個就是讓我們回到例程-2, 順序對我們來說沒什麼, 誰先誰後不一樣呢,只要能編譯通過,程式能執行, 就讓main()檔案總是放到最後吧.

那就讓我們來看另一個例程,讓我們看看這個方法是不是在任何時候都會起作用.

檔名 first.c

play2()

play1()

main()

例程-4

也許大部分都會看出來了,這就是經常用到的一種演算法, 函式巢狀, 那麼讓我們看看, play1和play2這兩個函式哪個放到前面呢?

這時就需要我們來使用第二種方法,使用宣告.

檔名 first.c

play1();

play2();

play2()

play1()

main()

例程-4

經歷了我的半天的嘮叨, 加上四個例程的說明,我們終於開始了用量變引起的質變, 這篇文章的主題.h檔案快要出現了。

一個大型的軟體專案,可能有幾千個,上萬個play, 而不只是play1,play2這麼簡單, 這樣就可能有n個類似 play1(); play2(); 這樣的宣告, 這個時候就需要我們想辦法把這樣的play1(); play2(); 也另行管理, 而不是把他放在.c檔案中, 於是.h檔案出現了.

檔名 first.h

play1();

play2();

檔名 first.c

#include 「first.h」

play2()

play1()

main()

例程-4

各位有可能會說,這位janders大蝦也太羅嗦了,上面這些我也知道, 你還講了這麼半天, 請原諒,如果說上面的內容80%的人都知道的話,那麼我保證,下面的內容,80%的人都不完全知道. 而且這也是我講述一件事的一貫作風,我總是想把一個東西說明白,讓那些剛剛接觸c的人也一樣明白.

上面是.h檔案的最基本的功能, 那麼.h檔案還有什麼別的功能呢? 讓我來描述一下我手頭的一個專案吧.

這個專案已經做了有10年以上了,具體多少年我們部門的人誰都說不太準確,況且時間並不是最主要的,不再詳查了。 是一個通訊裝置的前臺軟體, 原始檔大小共 51.6m, 大小共1601個檔案, 編譯後大約10m, 其龐大可想而知, 在這裡充斥著錯綜複雜的呼叫關係,如在second.

c中還有一個函式需要呼叫first.c檔案中的play1函式, 如何實現呢?

sencond.h 檔案

play1();

sencond.c檔案

***()

例程-5

在sencond.h檔案內宣告play1函式,怎麼能呼叫到first.c檔案中的哪個play1函式中呢?

是不是搞錯了,沒有搞錯, 這裡涉及到c語言的另一個特性:儲存類說明符.

c語言的儲存類說明符有以下幾個, 我來列表說明一下

說明符 用法

auto 只在塊內變數宣告中被允許, 表示變數具有本地生存期.

extern 出現在頂層或塊的外部變數函式與變數宣告中,表示宣告的物件

具有靜態生存期, 連線程式知道其名字.

static 可以放在函式與變數宣告中. 在函式定義時, 其只用於指定函式

名,而不將函式匯出到連線程式. 在函式宣告中,表示其後面會有

定義宣告的函式, 儲存類為static. 在資料宣告中, 總是表示定義

的宣告不匯出到連線程式.

無疑, 在例程-5中的second.h和first.h中,需要我們用extern標誌符來修飾play1函式的宣告,這樣,play1()函式就可以被匯出到連線程式, 也就是實現了無論在first.

c檔案中呼叫,還是在second.c檔案中呼叫,連線程式都會很聰明的按照我們的意願,把他連線到first.c檔案中的play1函式的定義上去, 而不必我們在second.

c檔案中也要再寫一個一樣的play1函式.

但隨之有一個小問題, 在例程-5中,我們並沒有用extern標誌符來修飾play1啊, 這裡涉及到另一個問題, c語言中有預設的儲存類標誌符. c99中規定, 所有頂層的預設儲存類標誌符都是extern . 原來如此啊, 哈哈.

回想一下例程-4, 也是好險, 我們在無知的情況下, 竟然也誤打誤撞,用到了extern修飾符, 否則在first.h中宣告的play1函式如果不被連線程式匯出,那麼我們在在play2()中呼叫他時, 是找不到其實際定義位置的 .

那麼我們如何來區分哪個標頭檔案中的宣告在其對應的.c檔案中有定義,而哪個又沒有呢? 這也許不是必須的,因為無論在哪個檔案中定義,聰明的連線程式都會義無返顧的幫我們找到,並匯出到連線程式, 但我覺得他確實必要的.

因為我們需要知道這個函式的具體內容是什麼,有什麼功能, 有了新需求後我也許要修改他, 我需要在短時間內能找到這個函式的定義, 那麼我來介紹一下在c語言中一個人為的規範:

在.h檔案中宣告的函式,如果在其對應的.c檔案中有定義,那麼我們在宣告這個函式時,不使用extern修飾符, 如果反之,則必須顯示使用extern修飾符.

這樣,在c語言的.h檔案中,我們會看到兩種型別的函式宣告. 帶extern的,還不帶extern的, 簡單明瞭,一個是引用外部函式,一個是自己生命並定義的函式.

最終如下:

sencond.h 檔案

extern play1();

上面洋洋灑灑寫了那麼多都是針對函式的,而實際上.h檔案卻不是為函式所御用的. 開啟我們專案的一個.h檔案我們發現除了函式外,還有其他的東西, 那就是全域性變數.

在大型專案中,對全域性變數的使用不可避免, 比如,在first.c中需要使用一個全域性變數g_test, 那麼我們可以在first.h中,定義 tpye g_test.

與對函式的使用類似, 在second.c中我們的開發人員發現他也需要使用這個全域性變數, 而且要與first.c中一樣的那個, 如何處理?

對,我們可以仿照函式中的處理方法,在second.h中再次宣告tpye g_test, 根據extern的用法,以及c語言中預設的儲存型別, 在兩個標頭檔案中宣告的tpye g_test,其實其儲存型別都是extern, 也就是說不必我們操心, 連線程式會幫助我們處理一切. 但我們又如何區分全域性變數哪個是定義宣告,哪個是引用宣告呢?

這個比函式要複雜一些, 一般在c語言中有如下幾種模型來區分:

1、 初始化語句模型

頂層宣告中,存在初始化語句是,表示這個宣告是定義宣告,其他宣告是引用宣告。c語言的所有檔案之中,只能有一個定義宣告。

按照這個模型,我們可以在first.h中定義如下tpye g_test=1;那麼就確定在first中的是定義宣告,在其他的所有宣告都是引用宣告。

2、 省略儲存型別說明

在這個模型中,所有引用宣告要顯示的包括儲存類extern, 而每個外部變數的唯一定義宣告中省略儲存類說明符。

這個與我們對函式的處理方法類似,不再舉例說明。

這裡還有一個需要說明,本來與本文並不十分相關,但前一段有個朋友遇到此問題,相信很多人都會遇到, 那就是陣列全域性變數。

他遇到的問題如下:

在宣告定義時,定義陣列如下:

int g_glob[100];

在另一個檔案中引用宣告如下:

int * g_glob;

在vc中,是可以編譯通過的, 這種情況大家都比較模糊並且需要注意,陣列與指標類似,但並不等於說對陣列的宣告起變數就是指標。 上面所說的的程式在執行時發現了問題,在引用宣告的那個檔案中,使用這個指標時總是提示記憶體訪問錯誤,原來我們的連線程式並不把指標與陣列等同,連線時,也不把他們當做同一個定義,而是認為是不相關的兩個定義,當然會出現錯誤。正確的使用方法是在引用宣告中宣告如下:

int g_glob[10];

並且最好再加上一個extern,更加明瞭。

extern int g_glob[10];

C語言中為什麼不需要庫函式和標頭檔案

1 c語言任何時候都需要庫函式和標頭檔案。c語言本身是沒有什麼作用的,它靠的就是函式庫來執行語句的,c語言就是由函式構成的。標頭檔案更是不能少了,但是隻有 include stdio.h 這個標頭檔案在整個程式裡只有printf和scanf這兩種輸出輸入語句時才可以省略 include stdio....

聽說h字尾的檔案是c語言的標頭檔案,不是c 的。c 的

lz的說法有誤。include只是文字包含,具體一點地說,在一般的實現中,只要是可以正常訪問的文字檔案,無論是什麼副檔名 甚至不含副檔名 前處理器僅僅把文字的內容複製到 include所在行並刪除此行,也就是用文字檔案的內容替換 include所在的這一行而已,而不會在 include進行時因為檔名...

c 中怎樣將類放在標頭檔案中,怎樣將類宣告放在標頭檔案,將類實現和主函式分別放在兩個原始檔裡?

小丁創業 實現的方法和詳細的操作步驟如下 1 第一步,開啟 zdvc 6.0 編譯器,然後選擇 新建 選項,見下圖,轉到下面的步驟。2 第二步,完成上述步驟後,選擇檔案,然後選擇c c 標頭檔案,在右側 的檔名中輸入要使用的標頭檔案的名稱,輸入名稱後單擊確認,見下圖,轉到下面的步驟。3 第三步,完成...