V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
ChristopherWu
V2EX  ›  程序员

C 语言是一门很难的编程语言,不懂编译原理、操作系统和计算机体系结构很难学明白...

  •  
  •   ChristopherWu · 2018-09-29 17:10:43 +08:00 · 7105 次点击
    这是一个创建于 2245 天前的主题,其中的信息可能已经有所发展或是发生改变。

    看以前自己写的一篇文章时有感: https://yonghaowu.github.io//2018/03/05/C_is_not_easy/ 萌新一个,抛砖引玉,欢迎 v 友指点

    /* #include <stdio.h> */
    /* #include <malloc.h> */
    int main(){
        char *c = malloc(10);
        c[0] = 'a';
        printf("hi, ");
        printf("%s\n", c);
        free(c);
        return 0;
    }
    

    为什么这个程序缺了头文件, 依然可以正常编译运行, 并且有正确的结果?


    /* #include <stdio.h> */
    /* #include <malloc.h> */
    /* #include <assert.h> */
    int main(){
       char *c = malloc(10);
       c[0] = 'a';
       printf("hi, ");
       printf("%s\n", c);
       assert(c[0] >= 0.0);
       free(c);
       return 0;
    }
    

    为啥这个程序, 加了 assert 又不行了呢?


    1. #include 只是把头文件引入进来, 头文件的作用是 包含函数的原型。
    2. linker (链接器)在链接这一步时,会根据头文件函数的原型去找. o 文件中的函数,然后链接进来
    3. 对于找不到的函数,各个编译器处理会有不同。gcc、clang 会推断这个函数的原型,如 printf 就是 void printf(char *c, char)
    4. 推断了原型后,因为每个 C 程序都默认会链接 stdlib 库( gcc 编译里有 nostdlib 选项,即不去默认链接 stdlib 的库),所以你正确的使用这个 C 语言函数,也是会找到对应的正确函数
    5. 所以程序编译时会有警告,依然编译通过,并且能正确运行。

    那为什么 assert 就不行了呢? 因为 assert 是一个宏,而不是函数,所以编译器不会像上述那样去处理。当没有引入 assert.h, 编译器便当它是函数来处理,最终 stdlib 里也找不到 assert 这个函数,就报错了。

    45 条回复    2018-09-30 15:48:49 +08:00
    innoink
        1
    innoink  
       2018-09-29 17:24:14 +08:00 via Android   ❤️ 5
    根据你说的,我得到的结论是,c 语言是一个充满历史包袱的语言
    LuffyGu
        2
    LuffyGu  
       2018-09-29 17:26:28 +08:00   ❤️ 5
    你要战,便作战。


    PHP 是世界上最好的语言!
    changhe626
        3
    changhe626  
       2018-09-29 17:48:40 +08:00
    你要战,便作战。


    PHP 是世界上最好的语言!
    Chowe
        4
    Chowe  
       2018-09-29 17:51:02 +08:00
    人生苦短,我用 python
    RobertYang
        5
    RobertYang  
       2018-09-29 17:51:58 +08:00 via Android   ❤️ 1
    TNT !启动!
    will0404
        6
    will0404  
       2018-09-29 17:53:34 +08:00 via iPhone   ❤️ 4
    读一遍 CSAPP,这都不算啥了。
    Raisu
        7
    Raisu  
       2018-09-29 17:57:35 +08:00 via Android
    @will0404 读完还是月薪 5k
    GTim
        8
    GTim  
       2018-09-29 18:02:44 +08:00   ❤️ 2
    看到这个帖子的第一直觉,难道不是编译原理、操作系统和计算机体系结构太难,所以有了 C 语言
    supuwoerc
        9
    supuwoerc  
       2018-09-29 18:16:52 +08:00
    越底层越难,人生苦短,我用地摊语言 js~
    583376938
        10
    583376938  
       2018-09-29 18:26:57 +08:00
    @Raisu 哈哈,内功
    Raisu
        11
    Raisu  
       2018-09-29 18:29:19 +08:00 via Android
    @583376938 内功都是假的,Milo Yip 那个书单第一部分我都看完了还是不在公司蹲坑,会套路才是真。
    hmzt
        12
    hmzt  
       2018-09-29 19:24:31 +08:00
    只是写起来繁琐,难在哪呢
    sbw
        13
    sbw  
       2018-09-29 19:30:39 +08:00
    printf 明明是 int __cdecl printf(const char *format, ...);
    ChristopherWu
        14
    ChristopherWu  
    OP
       2018-09-29 20:05:35 +08:00
    @Raisu @will0404 读完跟理解(融会贯通)还是有区别的。。
    ChristopherWu
        15
    ChristopherWu  
    OP
       2018-09-29 20:05:49 +08:00
    @sbw 大佬说的对。。
    zhzer
        16
    zhzer  
       2018-09-29 20:13:23 +08:00 via Android   ❤️ 2
    我用 python 我骄傲,我给项目打包票 耶
    >> UnicodeDecodeError
    luozic
        17
    luozic  
       2018-09-29 20:14:51 +08:00 via iPhone
    你这是要撸通用库? 一般的不都是撸个特定硬件和系统环境的软件或者直接就是硬件绑定的驱动,哪需要撸那没多,并且一般这种不是上 C++么?
    zaqmjuop
        18
    zaqmjuop  
       2018-09-29 21:02:36 +08:00 via Android   ❤️ 3
    汇编是一个更难,更高端的语言
    a1lenyang
        19
    a1lenyang  
       2018-09-29 21:07:20 +08:00   ❤️ 1
    @zaqmjuop 为什么不用机器码呢哈哈哈
    courage007
        20
    courage007  
       2018-09-29 21:09:33 +08:00 via Android
    是不是编译器预制了一个头文件,然后即使没有手动引用也不会报错?
    crist
        21
    crist  
       2018-09-29 21:28:08 +08:00
    人生苦短,我用胶水语言 Python~
    linxu
        22
    linxu  
       2018-09-29 21:54:34 +08:00   ❤️ 2
    @LuffyGu php 是 c 写的
    d18
        23
    d18  
       2018-09-29 22:00:34 +08:00
    我喜欢 C 语言,简单明了,没有黑魔法。
    zjsxwc
        24
    zjsxwc  
       2018-09-29 22:05:26 +08:00 via Android   ❤️ 1
    @d18

    信你有鬼了,各种骚宏,多到你怀疑人生
    newtype0092
        25
    newtype0092  
       2018-09-29 22:16:17 +08:00
    @zjsxwc 别的时髦语言使用了魔术道具,自己拿来学学就能露两手,C 是直接当着你的面玩无影手,原理全部告诉你,看完还是一脸懵逼。。。
    zwh2698
        26
    zwh2698  
       2018-09-29 22:21:36 +08:00 via Android   ❤️ 1
    瞎说,谭浩强的二级 c 语言书中前面几章就有讲这个问题。
    bobuick
        27
    bobuick  
       2018-09-29 22:34:18 +08:00
    c 光语法对话,很简单了。
    难的是,习惯了 web 开发的高级语言,各种库拿来操一下就出成果了。换成 C,操一个月不一定出来。
    xiyiailoli
        28
    xiyiailoli  
       2018-09-29 22:47:47 +08:00 via Android
    ⊙∀⊙!差不多同意,我学了操作系统后也有这种感觉,但现在有精力研究 c 还不如去 c++吧
    jecshcier
        29
    jecshcier  
       2018-09-29 22:48:51 +08:00 via iPhone
    @bobuick 哇操一个月都不出来,说明耐操阿,多爽,手动斜眼
    xeaglex
        30
    xeaglex  
       2018-09-30 00:12:32 +08:00
    我觉得是你没有习惯而已,C 的设计还是非常简洁优雅的,不像 CPP
    jiang42
        31
    jiang42  
       2018-09-30 01:03:59 +08:00 via iPhone
    @xeaglex 請回答,Cpp the good part 又名?🤪
    inoki
        32
    inoki  
       2018-09-30 01:33:17 +08:00 via Android
    手动 at 一下正在学的 x86 asm 和 arm 汇编😂
    Raisu
        33
    Raisu  
       2018-09-30 07:49:09 +08:00 via Android
    @ChristopherWu 什么叫理解?我还见过看完做完 算法导论 所有习题也只有几 K 的人啊
    kljsandjb
        34
    kljsandjb  
       2018-09-30 08:18:02 +08:00 via iPhone
    内功不是看书看的,看完书把习题做好 lab 吃透才算有效果
    ww2000e
        35
    ww2000e  
       2018-09-30 08:30:45 +08:00 via Android
    c 少个结束符啊,s%凑巧给你打出来了
    cgpiao
        36
    cgpiao  
       2018-09-30 08:41:53 +08:00 via iPhone
    我选 php 和 kotlin
    python 用着好难受,标准库用起来更糟心
    leido
        37
    leido  
       2018-09-30 08:57:29 +08:00 via Android
    @ww2000e 说的对,malloc 根本不保证初始化内存
    cangshui
        38
    cangshui  
       2018-09-30 09:21:07 +08:00 via Android
    小爱同学,帮我做一下 c 语音课后习题
    Chenamy2017
        39
    Chenamy2017  
       2018-09-30 09:31:45 +08:00
    学好 C 语言,就能理解计算机很多根本的问题了!
    nekoneko
        40
    nekoneko  
       2018-09-30 09:34:15 +08:00
    @Raisu 看完算法导论,发现我的高数水平提升了。。。
    Raisu
        41
    Raisu  
       2018-09-30 09:36:19 +08:00 via Android
    @nekoneko 数学证明挺好看的,公开课的老师也很搞笑。。。
    visionsmile
        42
    visionsmile  
       2018-09-30 09:45:46 +08:00   ❤️ 1
    C89 具有函数的隐式声明:
    [ISO/IEC 9899:1990 6.3.2.2]
    If the expression that precedes the parenthesized argument list in a function call consists solely of an identifier. and if no declaration is visible for this identifier, the identifier is implicitly declared exactly as if. in the innermost block containing the function call. the declaration
    ```c
    extern int idenfifrer () ;
    ```
    然而这个特性 C99 就废除掉了:
    [ISO/IEC 9899:1999 Foreword]
    - remove implicit function declaration
    likaka
        43
    likaka  
       2018-09-30 11:16:18 +08:00
    在 java 面前,c 就是个土老帽
    LuffyGu
        44
    LuffyGu  
       2018-09-30 13:11:41 +08:00
    @linxu C 语言是 B 语言开发的,但你不能说 C 没有 B 屌啊
    HidingKing
        45
    HidingKing  
       2018-09-30 15:48:49 +08:00
    write once,run anywhere
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3855 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 05:17 · PVG 13:17 · LAX 21:17 · JFK 00:17
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.