簡體   English   中英

C頭文件 - 良好實踐

[英]C Header Files - Good Practice

我習慣於Objective C頭文件,並且不確定如何在良好實踐中使用C頭文件。

在頭文件或.c文件中哪一個#include其他源文件?

是否同樣的想法適用於C。其中.c文件包含自己的頭文件。 和其他文件包括他們想要包含的源的.h文件?

是否有與Objective-C中@class用法相同的東西?

在.h文件中聲明指針並初始化它們/在.c文件中分配它們是一種好習慣嗎?

您通常以與Objective-C區分實現(.m)和接口(.h)文件相同的方式區分源文件和頭文件。 源文件包含可能執行的所有內容,頭文件包含有關其他源文件知道如何與該源文件通信的符號的足夠信息。

頭文件通常包含其他頭文件,因此您將在源文件和實現文件中看到#include #include#import操作完全相同,只是它不會自動檢查你是否#include同一個文件兩次。 所以C頭文件通常看起來像:

#ifndef __SOME_SYMBOL
#define __SOME_SYMBOL

    ... rest of header file here ...

#endif

其中只有一次包含確保頭文件主體的效果相同。

編輯:根據要求,更多關於此。 顯然你永遠不會做類似的事情:

#include "File.h"
#include "File.h"

但你可以很容易地得到類似的東西:

#include "FirstComplexThing.h"
#include "SecondComplexThing.h"

FirstComplexThing.h和SecondComplexThing.h都依賴於內部的東西,因此#include SimpleThing.h。 因此,您最終使用SimpleThing.h #included兩次,不會出現任何錯誤或遵循任何錯誤的設計模式。

C編譯器就像Objective-C編譯器一樣工作 - 每個源文件都是獨立編譯的,在鏈接器出現之前沒有概述。 #include是一個預處理程序指令,它具有與復制指定文件的內容並將它們粘貼到該位置的源文件相同的邏輯效果,因此,如果您最終將同一文件#included結束兩次,您可能會得到一些東西喜歡:

char *somePointer; // I'm from SimpleThing.h

... lots of other things ...

char *somePointer; // I'm from SimpleThing.h

並且編譯器將停止並返回同一事件被聲明兩次的錯誤。 Objective-C中的#import通過簡寫'#include來避免這種情況,但前提是你還沒有#included那個文件'。 C#ifndef / #define / #endif約定實現與#import相同的東西,因為#ifndef / #endif對說如果指定的預處理器符號(在我的例子中是__SOME_SYMBOL,那么它們之間的東西應該傳遞給編譯器;它往往是從該頭文件的名稱派生的名稱,但確切的約定不同)尚未定義。 它不會是第一次遇到構造。 因為它是在構造內定義的,所以第二次遇到相同的#ifndef時,所以匹配#endif的東西不會被傳遞。

雖然這是一個樣式問題,但通常情況是每個C文件都有一個直接連接到它的H文件。

顯然,C中沒有類,但如果你的意思是一個類似的構造:

@class SomeClass;

@interface SomeOtherClass: NSObject
{
      SomeClass *otherClass; // I can reference SomeClass without importing
                             // the interface file because I've declared the
                             // type above
}

- (void)whatever;
@end

這實際上是聲明和定義之間的正常C區別。 如果您執行以下操作,則會遇到問題:

struct SomeStruct;

struct SomeOtherStruct
{
    struct SomeStruct otherStruct;
};

因為編譯器沒有足夠的信息。 它不知道SomeStruct應該有多大,所以它無法解決SomeOtherStruct應該如何布局。 但是,這完全有效:

struct SomeStruct;

struct SomeOtherStruct
{
    struct SomeStruct *otherStruct;
};

因為指針的大小總是已知的,無論它指向什么。 您經常會看到具有不透明類型的C庫僅通過指針描述這些類型(有時為void * ,但並非總是如此 - 例如stdio.h使用FILE * )或者僅給出一個整數(包括OpenGL,特別是)。 所以他們確保你有一些編譯器會知道大小的東西,而不必告訴你他們與之關聯的數據,或者給你任何方法來嘗試自己操作它。

將指針放在頭文件中是非常好的做法(假設顯然是全局公開事物的好方法)。 同樣的事情通常在Objective-C中完成,盡管原因略有不同,例如

// interface/header file

extern NSString *someGlobalIdentifier;

和:

// implementation/source file

NSString *someGlobalIdentifier = @"somethingOrOther";

在Objective-C中,因為您可以測試身份而不是總是必須測試相等性,但基本上相同的規則適用於C,因為將表示事物的引用(無論是指針或其他)放入是否正常標題並在源文件中創建或聲明該事物。 實際上,如果你開始在頭文件中放置聲明,那么當程序鏈接時你最終會出錯,因為多個源文件會認為它們聲明了這一點。

- > #include正在c和c中工作。 - >但通常在目標c中,總是使用#import。 - > #include和#import是不同的,當你使用#include編譯器生成一個單獨的.h文件副本時,如果你使用#import那么編譯器一次只生成一個副本

是否有與Objective-C中@class用法相同的東西? - >沒有沒有任何其他等價物。在.h文件中聲明指針並初始化它們/在.c文件中分配它們是不錯的做法? - >是的如果您的對象是公共的,那么您必須在.h文件中聲明,但始終是在構造函數中初始化它的好習慣。

這就是我最終弄清楚如何正確地做到這一點的方法。 經過長時間的嘗試和失敗之前曾經是一件簡單的事情。

    //this is the mechanics.h file

    #ifndef ProjectA_mechanics_h
    #define ProjectA_mechanics_h

    #ifdef __cplusplus
    extern "C" {
    #endif

    int funcAdd (int A, int B);


    #ifdef __cplusplus
    }
    #endif

    #endif

    // this is the mechanics.c file

    #include "mechanics.h"
    #include <math.h>

    int funcAdd (int A, int B)
    {
        return A + B;
    }

math.h有“只是因為”

玩得開心,這對於吸吮而言

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM