V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
gegeligegeligo
V2EX  ›  问与答

为什么 C 语言被设计成函数需要先声明才能被使用?

  •  
  •   gegeligegeligo · 28 天前 · 1563 次点击

    纯粹是因为历史问题吗

    19 条回复    2024-08-23 06:42:05 +08:00
    anytk
        1
    anytk  
       28 天前 via Android
    编译和链接,函数声明表明其符号特征,在链接时才能定位精确和一致。
    ho121
        2
    ho121  
       28 天前 via Android
    印象当中不是这样。
    可以不声明直接调用,编译期间会有个 warning ,运气不好的话链接会失败
    NightFlame
        3
    NightFlame  
       28 天前
    @ho121 那你记错了
    iOCZS
        4
    iOCZS  
       28 天前
    怎么隐藏函数呢?
    shadowyue
        5
    shadowyue  
       28 天前   ❤️ 1
    施法当然要大声的把招式名称念出来才帅气
    proxytoworld
        6
    proxytoworld  
       28 天前
    确实是历史原因,c99 标准还只能在函数开头声明变量。
    proxytoworld
        7
    proxytoworld  
       28 天前
    @NightFlame 系统库可以这样玩,不引入头文件,直接使用函数也能跑
    tianhehechu
        8
    tianhehechu  
       28 天前   ❤️ 2
    为了提高编译效率,降低实现复杂度,否则编译时就要遍历整个代码去寻找这个函数。C 标准出来时,机器性能没那么高,编译速度很重要。
    darksword21
        9
    darksword21  
       28 天前 via iPhone
    刚开始学的时候感觉还挺符合直觉的….可能就是按直觉设计的吧
    hangbale
        10
    hangbale  
       28 天前
    对编译器友好
    Mithril
        11
    Mithril  
       28 天前
    是的,纯粹是历史问题。

    很久以前这种前置声明可以让你的编译器只遍历一遍编译单元就完成编译。但现在机器性能都很好,一般也都推荐你一个文件不要搞太大。所以你多扫几遍也是能用的。

    按照现在的性能来说,就相当于你每个代码文件都几个 G 到十几个 G 那么大,那你这编译器扫几遍你内存就爆炸了。
    enchilada2020
        12
    enchilada2020  
       28 天前 via Android
    @proxytoworld 我记得是 C99 以前只能在开头 从 C99 开始可以在任意地方声明了
    proxytoworld
        13
    proxytoworld  
       28 天前
    @enchilada2020 查了一下确实是,c89 只能在开头,
    ho121
        14
    ho121  
       28 天前 via Android   ❤️ 1
    @NightFlame 抱歉,我的印象比较久了。我测试了一下,用以前旧的 C89 标准是可以的。C99 标准不允许了。

    两个 c 文件


    ~ $ cat a.c
    int main(){
    f();
    }
    ~ $ cat b.c
    void f(){}

    用 C89 编译,只给了个 warning:

    ~ $ clang -std=c89 -Wall a.c b.c
    a.c:2:5: warning: implicit declaration of function 'f' [-Wimplicit-function-declaration]
    2 | f();
    | ^
    1 warning generated.


    用 C99 编译,不通过:

    ~ $ clang -std=c99 -Wall a.c b.c
    a.c:2:5: error: call to undeclared function 'f'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
    2 | f();
    | ^
    1 error generated.
    NightFlame
        15
    NightFlame  
       28 天前
    @ho121 #14 学习到了
    june4
        16
    june4  
       28 天前
    要手动同步实现和头文件,不嫌麻烦吗
    象 typescript 这种,直接由实现文件自动生成头文件不是更好?
    gegeligegeligo
        17
    gegeligegeligo  
    OP
       28 天前 via Android
    @june4 对。。。我也觉得很麻烦,但是要做嵌入式的话,是只能用 c 的
    James369
        18
    James369  
       28 天前
    这点确实不好用,特别是同一个文件里面,不声明只能调用写在前头的函数
    msg7086
        19
    msg7086  
       27 天前
    先声明再使用,是因为没有一个机制去提取声明然后做成索引。
    你要搞个通过源代码自动生成头文件的东西,那就也能做到了。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1971 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 22ms · UTC 16:19 · PVG 00:19 · LAX 09:19 · JFK 12:19
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.