【问题标题】:Standard libraries included multiple times over several files?标准库在多个文件中包含多次?
【发布时间】:2015-02-15 14:39:38
【问题描述】:

在 K&R 书 (p59)(编辑:第二版,涵盖 ANSI C)中,建议将较大的项目拆分为多个文件更容易。在每个文件中,像往常一样在顶部包含几个库:例如getop.c 需要 stdio.h,stack.c 和 main.c 也需要。

sn-ps 是这样的:

//main.c
#include <stdio.h>
#include <stdlib.h>
#include "calc.h"
int main(void)
{
    //etc
}


//getop.c
#include <stdio.h>
#include <ctype.h>
#include "calc.h"
getop()
{
    /*code*/
}

//stack.c
#include <stdio.h>
#include "calc.h"
void push(double val)
{
    //code
}

我无法弄清楚在一个项目中多次包含标准库是如何工作的。当然,为了让自定义.c文件能够访问内置函数,我们需要包含#include &lt;header.h&gt;,以便他们知道printf()getchar()等的存在,但不会这样如果 stdio.h 被包含四次而不是一次(如果所有内容都放在一个文件中),方法会增加最终程序的大小?

K&R 确实指出,将程序拆分为多个文件最终会使维护所有 .h 文件变得更加困难。

我想我真正要问的是编译器如何找出一个库在一个项目中被#include 多次的问题。

我已经阅读了使用 include guards 的内容,但这个实现似乎不需要,因为它们处理的是确保不包含两次相同的代码位,如:

文件“module.h”

#ifndef MODULE_H
#define MODULE_H

struct foo {
    int member;
};

#endif /* MODULE_H */

文件“mod2.h”

#include "module.h"

文件“prog.c”

#include "module.h"
#include "mod2.h"

refs

【问题讨论】:

标签: c compiler-construction c-preprocessor stdio kernighan-and-ritchie


【解决方案1】:

我想我真正要问的是编译器如何找出一个库在一个项目中被#include 多次的问题。

#include &lt;stdio.h&gt; 不包含库,您只需包含它的声明,因此编译器知道存在哪些函数。链接器负责包含一个库并将所有内容放在一起。

【讨论】:

    【解决方案2】:

    因为他们使用了一种叫做include guards的东西,假设你自己的包含文件被多次包含,那么你可以这样做

    MyHeader.h

    #ifndef MY_HEADER_H
    #define MY_HEADER_H
    /* file content goes here */
    #endif /* MY_HEADER_H */
    

    然后你有另一个标题

    **AnotherHeader.h**
    
    #ifndef MY_ANOTHER_HEADER_H
    #define MY_ANOTHER_HEADER_H
    #include "MyHeader.h"
    /* file content goes here */
    #endif /* MY_ANOTHER_HEADER_H */
    

    在你的程序中

    ma​​in.c

    /* 
     * MY_HEADER_H is undefined so it will be defined and MyHeader.h contents 
     * will be included.
     */
    #include "MyHeader.h" 
    /*
     * MY_HEADER_H is defined now, so MyHeader.h contents will not be included
     */
    #include "AnotherHeader.h"
    
    int main()
    {
        return 0;
    }
    

    由于每个编译单元只包含一次包含的文件,因此生成的二进制大小不会增加,此外,包含头文件只会增加编译文件的大小,例如在这些头文件中声明了字符串文字,否则它们只提供向编译器提供有关如何调用给定函数的信息,即如何将参数传递给它以及如何存储它的返回值。

    【讨论】:

    • __MY_HEADER_H__ 是保留名称
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-28
    • 1970-01-01
    • 2012-06-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多