简体   繁体   English

C头文件 - 良好实践

[英]C Header Files - Good Practice

I am used to Objective C header files and am not sure how C header files are used in terms of good practice. 我习惯于Objective C头文件,并且不确定如何在良好实践中使用C头文件。

Where would one #include other source files, in the header file or the .c file? 在头文件或.c文件中哪一个#include其他源文件?

Does the same idea apply to C where .c files include their own header files. 是否同样的想法适用于C。其中.c文件包含自己的头文件。 and other files include the .h files of the source they want to include? 和其他文件包括他们想要包含的源的.h文件?

Is there anything equivalent to the @class usage in Objective-C? 是否有与Objective-C中@class用法相同的东西?

Is it good practice to declare pointers in the .h file and initialize them/alloc them in the .c file? 在.h文件中声明指针并初始化它们/在.c文件中分配它们是一种好习惯吗?

You normally distinguish between source and header files in the same way that Objective-C differentiates between implementation (.m) and interface (.h) files. 您通常以与Objective-C区分实现(.m)和接口(.h)文件相同的方式区分源文件和头文件。 Source files contain everything that may execute, header files contain enough information about symbols that other source files know how to communicate with that source file. 源文件包含可能执行的所有内容,头文件包含有关其他源文件知道如何与该源文件通信的符号的足够信息。

Header files often include other header files, so you'll see #include in both source and implementation files. 头文件通常包含其他头文件,因此您将在源文件和实现文件中看到#include #include operates exactly like #import except that it doesn't automatically check whether you've #included the same file twice. #include#import操作完全相同,只是它不会自动检查你是否#include同一个文件两次。 So C header files often look something like: 所以C头文件通常看起来像:

#ifndef __SOME_SYMBOL
#define __SOME_SYMBOL

    ... rest of header file here ...

#endif

Which has the same effect of ensuring the main body of the header file is included only once. 其中只有一次包含确保头文件主体的效果相同。

EDIT: more on this, as per request. 编辑:根据要求,更多关于此。 Obviously you'd never do something like: 显然你永远不会做类似的事情:

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

But you can easily end up with something like: 但你可以很容易地得到类似的东西:

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

Where both FirstComplexThing.h and SecondComplexThing.h rely on something inside and hence #include SimpleThing.h. FirstComplexThing.h和SecondComplexThing.h都依赖于内部的东西,因此#include SimpleThing.h。 So you end up with SimpleThing.h #included twice, without making any sort of error or following any bad design pattern. 因此,您最终使用SimpleThing.h #included两次,不会出现任何错误或遵循任何错误的设计模式。

C compilers work just like Objective-C compilers — each source file is compiled on its own, in isolation, with no overview until the linker comes along. C编译器就像Objective-C编译器一样工作 - 每个源文件都是独立编译的,在链接器出现之前没有概述。 #include is a preprocessor directive that has the same logical effect as copying the contents of the named file and pasting them into your source file at that location, so if you end up the same file #included twice you'll probably end up with something like: #include是一个预处理程序指令,它具有与复制指定文件的内容并将它们粘贴到该位置的源文件相同的逻辑效果,因此,如果您最终将同一文件#included结束两次,您可能会得到一些东西喜欢:

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

... lots of other things ...

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

And the compiler will stop with an error that the same thing is declared twice. 并且编译器将停止并返回同一事件被声明两次的错误。 #import in Objective-C avoids that by being shorthand for '#include, but only if you haven't already #included that file'. Objective-C中的#import通过简写'#include来避免这种情况,但前提是你还没有#included那个文件'。 The C #ifndef/#define/#endif convention achieves the same thing as #import because the #ifndef/#endif pair say that the stuff in between should be passed on to the compiler if the nominated preprocessor symbol (__SOME_SYMBOL in my example; it tends to be a name derived from the name of that header file but exact conventions vary) hasn't been defined. C#ifndef / #define / #endif约定实现与#import相同的东西,因为#ifndef / #endif对说如果指定的预处理器符号(在我的例子中是__SOME_SYMBOL,那么它们之间的东西应该传递给编译器;它往往是从该头文件的名称派生的名称,但确切的约定不同)尚未定义。 It won't have been the first time the construct is encountered. 它不会是第一次遇到构造。 Because it is defined inside the construct, it will have been when the same #ifndef is encountered the second time, so the stuff up to the matching #endif won't be passed on. 因为它是在构造内定义的,所以第二次遇到相同的#ifndef时,所以匹配#endif的东西不会被传递。

Although it's a question of style, it is very often the case that each C file has one H file that is directly connected to it. 虽然这是一个样式问题,但通常情况是每个C文件都有一个直接连接到它的H文件。

There are no classes in C, obviously, but if you mean a construct like: 显然,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

That's actually the normal C distinction between declarations and definitions. 这实际上是声明和定义之间的正常C区别。 You'll have a problem if you do something like: 如果您执行以下操作,则会遇到问题:

struct SomeStruct;

struct SomeOtherStruct
{
    struct SomeStruct otherStruct;
};

Because the compiler doesn't have enough information. 因为编译器没有足够的信息。 It doesn't know how large SomeStruct should be, so it can't work out how SomeOtherStruct should be laid out. 它不知道SomeStruct应该有多大,所以它无法解决SomeOtherStruct应该如何布局。 However, this is completely valid: 但是,这完全有效:

struct SomeStruct;

struct SomeOtherStruct
{
    struct SomeStruct *otherStruct;
};

Because the size of a pointer is always known, irrespective of what it is pointing to. 因为指针的大小总是已知的,无论它指向什么。 You'll often see that C libraries with opaque types describe those types by pointer only (sometimes to void * , but not always — eg stdio.h uses FILE * ) or just give you an integer (including OpenGL, notably). 您经常会看到具有不透明类型的C库仅通过指针描述这些类型(有时为void * ,但并非总是如此 - 例如stdio.h使用FILE * )或者仅给出一个整数(包括OpenGL,特别是)。 So they ensure you've something that the compiler will know the size of without having to tell you what data they're associating with it or giving you any way to try to manipulate it yourself. 所以他们确保你有一些编译器会知道大小的东西,而不必告诉你他们与之关联的数据,或者给你任何方法来尝试自己操作它。

It's perfectly good practice to put pointers in the header file (assuming it's good practice to expose the thing globally, obviously). 将指针放在头文件中是非常好的做法(假设显然是全局公开事物的好方法)。 The same thing is often done in Objective-C, albeit for slightly different reasons, eg 同样的事情通常在Objective-C中完成,尽管原因略有不同,例如

// interface/header file

extern NSString *someGlobalIdentifier;

And: 和:

// implementation/source file

NSString *someGlobalIdentifier = @"somethingOrOther";

In Objective-C that's because you can then test identity rather than always having to test equality, but basically the same rules apply to C with respect to it being normal to put the reference (be it a pointer or whatever) that represents a thing into the header and create or declare the thing in a source file. 在Objective-C中,因为您可以测试身份而不是总是必须测试相等性,但基本上相同的规则适用于C,因为将表示事物的引用(无论是指针或其他)放入是否正常标题并在源文件中创建或声明该事物。 In fact, if you start putting declarations in the header file you'll end up with errors when the program comes to link because multiple source files will think they declare the thing. 实际上,如果你开始在头文件中放置声明,那么当程序链接时你最终会出错,因为多个源文件会认为它们声明了这一点。

->#include is working in c and objective c. - > #include正在c和c中工作。 ->But generally in objective c, always used #import. - >但通常在目标c中,总是使用#import。 ->#include and #import are different, when you used #include compiler generate one separate copy of .h file, and if you used #import then compiler generate only one copy at a time - > #include和#import是不同的,当你使用#include编译器生成一个单独的.h文件副本时,如果你使用#import那么编译器一次只生成一个副本

Is there anything equivalent to the @class usage in Objective-C? 是否有与Objective-C中@class用法相同的东西? -> No there is no any other equivalent Is it good practice to declare pointers in the .h file and initialize them/alloc them in the .c file? - >没有没有任何其他等价物。在.h文件中声明指针并初始化它们/在.c文件中分配它们是不错的做法? -> Yes if your object is public, then you must declare in .h file, but always is good practice that initialize them it in constructor. - >是的如果您的对象是公共的,那么您必须在.h文件中声明,但始终是在构造函数中初始化它的好习惯。

This is how I finally figured out how to do this properly. 这就是我最终弄清楚如何正确地做到这一点的方法。 After long time of trying and failing at what used to be a simple thing. 经过长时间的尝试和失败之前曾经是一件简单的事情。

    //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 is there "just because" math.h有“只是因为”

have fun, dang this sucked for while 玩得开心,这对于吸吮而言

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 将类扩展提取到单独的头文件中以进行Objective-C中的单元测试是否是一种好习惯? - Is this a good practice to extract class extension into a separate header file for unit testing purposes in Objective-C? 目标C-分配对象的良好做法 - Objective C - object allocating good practice 良好实践/不良实践-指针和设置值-目标C - Good practice / Bad Practice - Pointers and setting values - Objective C 使用NSURLConnection及其回调的良好做法? Objective-C的 - Good practice using NSURLConnection and its callbacks? Objective-C 目标C:检查JSON值是否是您期望的类型,这是一种好习惯吗? - Objective C: Is it good practice to check JSON values if it is the type you expect? 强迫开发人员遵守目标C中的协议是一种好习惯吗? - Is it a good practice to force developer to comply with a protocol in objective C? 避免在目标C中声明指向BOOL类型的指针是一种好习惯吗? - Is it good practice to avoid declaring a pointer to BOOL type in objective C? 使用#define,好的做法? - Using #define, good practice? 是#define PFUser的良好做法 - is #define PFUser good practice 扩展NSError是一个好习惯 - Is it a good practice to extend NSError
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM