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

2018-09-29 17:10:43 +08:00
 ChristopherWu

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

7142 次点击
所在节点    程序员
45 条回复
Raisu
2018-09-30 09:36:19 +08:00
@nekoneko 数学证明挺好看的,公开课的老师也很搞笑。。。
visionsmile
2018-09-30 09:45:46 +08:00
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
2018-09-30 11:16:18 +08:00
在 java 面前,c 就是个土老帽
LuffyGu
2018-09-30 13:11:41 +08:00
@linxu C 语言是 B 语言开发的,但你不能说 C 没有 B 屌啊
HidingKing
2018-09-30 15:48:49 +08:00
write once,run anywhere

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

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

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

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

© 2021 V2EX