加载中...
从零接触C语言(初览)-I: 理解编程 和 C语言

从零接触C语言(初览)-I: 理解编程 和 C语言

周二 3月 18 2025
2309 字 · 9 分钟

写在开头

在正式开始认识C语言之前, 我们可以先从一个抽象但简单的角度, 来聊一聊编程

编程是什么?

在我个人看来, 编程 是人与计算机之间交流的一种方式

人可以把想法告诉计算机, 而计算机会尝试理解这些想法, 并给出响应. 这种响应, 完全依赖于人给出的指令

比如, 如果你告诉计算机要显示一张图片, 它就只会显示一张图片; 如果你让它播放一首音乐, 它就只会播放音乐. 这其实就是一种交流

交流通常是需要媒介的

在人类社会中, 人与人之间靠语言沟通. 如果两个人要顺利交流, 前提是必须使用一种彼此都能理解的语言, 比如中文

当然, 如果两人之间没有一种彼此都能理解的语言, 也能借助翻译工具进行交流

人与计算机之间的交流, 也同样如此


最初, 人与计算机的交流, 是通过简单却复杂的二进制完成的

举个例子来帮助理解:

假设有一个房间, 里面有一排8个灯泡和一扇门, 灯泡只存在两种状态

如果规定:

  • 8个灯泡状态为 时, 表示开门
  • 8个灯泡状态为 时, 表示关门

那么, 这8个灯泡的状态组合就形成了了一种表达信息的媒介

人与计算机进行交流是类似的思路: 通过一段特定组合的二进制数据, 让计算机理解其所代表的含义, 就能与计算机进行交流

例如, 一段二进制数据10000011可以表示「加法运算」. 将它交给计算机, 计算机就知道要执行加法运算

这是一种低级但有效的语言, 它之所以能被计算机理解, 是因为计算机设计者赋予了它这种”语言”的含义

事实上, 二进制, 就是计算机真正能够理解的语言

但直接使用 二进制与计算机交流, 意味着每个”对话”都需要用一长串没有语义的数字进行, 这太费劲了

所以, 在二进制的基础上, 助记符诞生了: 用一个更方便人记忆的词, 表示计算机能理解的特定二进制数据段

比如, ADD表示10000011, 那么要让计算机理解 需要进行加法运算, 就不用告诉计算机10000011, 只需要告诉它ADD, 它就能够理解需要加法运算

基于这种思路, 汇编语言诞生了, 汇编语言结合了助记符、操作数、寄存器等概念, 形成一种人与计算机交流的媒介

再后来, 为了更方便与计算机进行交流, 所使用的语言也越来越向人类语言发展

直到出现了一门简明、高效的集大成者, 也就是本篇文章的重点: C语言

用C语言告诉计算机进行加法运算, 只需使用+, 计算机就能理解需要进行加法运算

如何理解C语言?

你可以把C语言(或任何高级编程语言), 想象成人类和计算机”都能听懂”的”普通话”

  • 计算机的”母语”是二进制 (比如10000011) , 但人类用二进制和它交流就像用摩斯密码聊天一样, 效率极低

  • 而C语言, 它用人类能看懂的关键字(ifforprintf)和符号(+-=)作为与计算机交流的指令

    虽然计算机不能直接理解这些关键字, 但是可以使用工具把这些指令翻译成计算机能执行的二进制

举个栗子🌰:

二进制是计算机真正能够理解的语言, 你想让计算机算1 + 1:

  • 使用二进制: 可能要写一长串101010...(晕)

  • 使用C语言: 直接写1 + 1

    但计算机看不懂, 所以编译器(翻译官)会帮你把1 + 1转成二进制, 计算机就能进行1+1运算

从打印Hello World开始

下面尝试编写并运行这个可能是你接触到的第一个C语言程序

打开终端, 运行WSL, 使用neovim创建main.c文件, 在文件中输入内容:

image-20250723115859201

C
#include <stdio.h>

int main() {
    printf("Hello World");
    
    return 0;
}

保存并关闭文件, 在终端中执行以下命令, 将C语言代码编译成可以被系统运行的程序:

BASH
gcc main.c

你会发现, 当前目录下多出了一个名为a.out的文件. 这个文件的颜色可能与你写的main.c文件不同, 因为它是一个可以被执行的二进制程序

你可以将它类比为Windows中的.exe文件

gcc是C语言代码的一种编译器

可以使用gcc将人可以看懂的C语言代码, 编译成操作系统可以看懂的二进制

然后操作系统才能去执行

在命令行输入./a.out, 并按下回车:

可以看到终端中出现了Hello World⏎的字样

恭喜你!你刚刚成功运行了 可能是你人生中的第一个C语言程序!


再来回看这段代码

C
#include <stdio.h>

int main() {
    printf("Hello World");
    
    return 0;
}

即使你从没接触过C语言, 大概也能从字面上猜出printf("Hello World")的含义:

  • print是英文中的”打印”
  • printf()这个”命令”的作用, 就是在终端中打印出一段文本

所以整段代码的效果就是: 向屏幕输出Hello World

类似printf()这样的可以被调用、执行、完成一些功能的”命令”, 在C语言中, 被称为函数(Function)

现阶段不需要理解什么是函数, 只需要与这个单词混个脸熟就好了

代码中的main()也是一个函数

从这个代码开始, 让我们来开始逐步认识C语言

C语言程序的入口

上面例子中的代码, 已经是一个非常简单的C语言代码了, 它只有一个功能, 那就是运行之后向屏幕输出Hello World

但它不是最简单的C语言程序, 最简单的C语言程序代码, 是这样的:

C
int main() {
    return 0;
}

向上面一样, 执行gcc main.c编译代码, 生成一个可执行文件

但, 这个可执行程序并没有实现任何实际功能, 至少没有像上例中打印一些东西:

那么, 再尝试一下, 如果main.c文件一行代码都没有, 是一个空文件, 还能编译出一个可执行程序吗?

从结果来看, 编译失败了

不仅没有编译出可执行程序, 而且在编译过程中, 还报出了错误

报错的大概意思是 “xxx路径下的crt1.o中的_start_函数中使用的main没有被定义”

虽然不知道真正原因 但是这可以告诉我们一个结论:

一个标准的C语言程序, 至少要有一个main()函数, 编译器才能将C语言代码编译成可执行程序

而这个 main()函数, 就是C语言程序中用户代码的入口

用更加书面的形式表述就是:

“在标准C语言环境下, 要生成可执行程序必须提供main()函数作为程序入口

使用空源文件编译, 虽然能通过编译阶段, 但会因缺少main()而在链接阶段失败, 因为C运行时初始化代码需要调用它

这是由C语言标准规定的”


main()函数是C语言程序的入口

这意味着, C语言标准程序, 用户如果要实现什么功能, 就需要在main()函数中实现对应的代码

就像:

C
#include <stdio.h>

int main() {
    printf("Hello World");
    
    return 0;
}

main()函数中执行了printf("Hello World");

最终编译出来的程序, 执行之后可以打印Hello World

不直接或间接在main()函数中调用的语句, 是不会执行的


Thanks for reading!

从零接触C语言(初览)-I: 理解编程 和 C语言

周二 3月 18 2025
2309 字 · 9 分钟