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

2018 年 9 月 29 日
 huoru

看以前自己写的一篇文章时有感: 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 这个函数,就报错了。

8149 次点击
所在节点    程序员
45 条回复
innoink
2018 年 9 月 29 日
根据你说的,我得到的结论是,c 语言是一个充满历史包袱的语言
LuffyGu
2018 年 9 月 29 日
你要战,便作战。


PHP 是世界上最好的语言!
changhe626
2018 年 9 月 29 日
你要战,便作战。


PHP 是世界上最好的语言!
Chowe
2018 年 9 月 29 日
人生苦短,我用 python
RobertYang
2018 年 9 月 29 日
TNT !启动!
will0404
2018 年 9 月 29 日
读一遍 CSAPP,这都不算啥了。
Raisu
2018 年 9 月 29 日
@will0404 读完还是月薪 5k
yemoluo
2018 年 9 月 29 日
看到这个帖子的第一直觉,难道不是编译原理、操作系统和计算机体系结构太难,所以有了 C 语言
supuwoerc
2018 年 9 月 29 日
越底层越难,人生苦短,我用地摊语言 js~
583376938
2018 年 9 月 29 日
@Raisu 哈哈,内功
Raisu
2018 年 9 月 29 日
@583376938 内功都是假的,Milo Yip 那个书单第一部分我都看完了还是不在公司蹲坑,会套路才是真。
hmzt
2018 年 9 月 29 日
只是写起来繁琐,难在哪呢
sbw
2018 年 9 月 29 日
printf 明明是 int __cdecl printf(const char *format, ...);
huoru
2018 年 9 月 29 日
@Raisu @will0404 读完跟理解(融会贯通)还是有区别的。。
huoru
2018 年 9 月 29 日
@sbw 大佬说的对。。
zhzer
2018 年 9 月 29 日
我用 python 我骄傲,我给项目打包票 耶
>> UnicodeDecodeError
luozic
2018 年 9 月 29 日
你这是要撸通用库? 一般的不都是撸个特定硬件和系统环境的软件或者直接就是硬件绑定的驱动,哪需要撸那没多,并且一般这种不是上 C++么?
zaqmjuop
2018 年 9 月 29 日
汇编是一个更难,更高端的语言
a1lenyang
2018 年 9 月 29 日
@zaqmjuop 为什么不用机器码呢哈哈哈
courage007
2018 年 9 月 29 日
是不是编译器预制了一个头文件,然后即使没有手动引用也不会报错?

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/493916

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX