C 语言教程: Hello, World!
C 是一个低级别的语言,它为许多现代语言提供灵感,找到 c 语言的一部分。C 语言的一个问题是指针。你可能对 C 语言其他东西都很熟悉,但指针总会让你抓狂
C 是一个低级别的语言。但在以前不是,当人们还在使用穿孔卡编写程序时,C 是一种可以摆脱汇编(例如 Assembly)这个苦差事的一种方式。
但在现代,当代语言提供了 C 语言发明时所不存在的各种特性,这意味着 C 是一种非常基础的语言并没有很多特性。你可以使用 C 语言为你做任何事情。
那为什么我们今天还在使用 C 语言。
- 作为一种学习工具:C 不仅是计算历史上令人尊敬的一段,而且它以一种现代语言所没有的方式连接计算机。当你学习 C 语言时,你会了解软件如何在低层次与计算机内存交互。这里没有安全带。你会写出崩溃的软件,这就是乐趣的一部分!
- 作为有用的工具:C 仍然用于某些应用程序,例如构建操作系统或嵌入式系统。 尽管 Rust 编程语言也在关注这两个领域。
如果你熟悉其它语言,那么你会得 C 语言很简单,C 语言为许多语言提供灵感。你会在 Go、Rust、Swift、Python、JavaScript、Java 和各种语言中看到它的一部分。你可会对 C 语言感到熟悉。
C 语言的一个问题是指针。你可能对 C 语言其他东西都很熟悉,但指针行为非常奇怪。指针背后的概念您可能是已经知道,但 C 语言强制您对指针进行明确理解。
因为一旦你理解指针,它们就会变得容易。但在那一刻之前,它们都是滑溜溜的鳗鱼,让你根本抓不住它。
Hello, World!
这是 C 程序的典型示例。 几乎每个人都知道如何编写它。
#include <stdio.h>
int main(void) {
printf("Hello, World!\n");
}
让我们看看代码都包含什么,首先 /*
和 */
之间的任何内容都是注释,编译器将完全忽略它。 //
同行之后任何内容也是如此。这允许你给自己代码添加注释或者留言,当你在遥远的未来回来阅读你的代码时,你就会知道你到底想做什么。
那么,#include 是什么? ,它告诉 C 预处理器提取另一个文件的内容并将其插入到代码中。
你可能会问——什么是 C 预处理器? 好问题。 编译有两个阶段:预处理器和编译器。 任何以井号 #
开头的东西都是预处理器在编译器开始之前运行的东西。常见的预处理器指令是 #include 和 #define。
在 C 预处理器完成所有预处理后,结果就准备好给编译器使用,编译器生成汇编代码机器代码或者任何它要执行的操作。机器代码是 CPU 可以理解的语言,CPU 可以非常快速地理解它。 这是 C 程序之所以快的原因之一。
现在我们不需要理解编译的技术细节; 只需知道您的代码通过预处理器运行,然后它的输出通过编译器运行,最后生成一个可执行文件供您运行。
那剩下的行呢? <stdio.h> 是什么? 这就是所谓的头文件。 是末尾的 .h
泄露它是什么。它将是您将逐渐要了解和喜爱的标准 I/O(stdio) 头文件。 它使我们能够访问一堆 I/O 函数。
对于我们的示例程序,我们正在向终端打印字符串 “Hello, World!”,因此我们需要访问 printf() 函数来执行此操作。
<stdio.h> 文件为我们提供这种访问能力。如果我们尝试在没有 #include <stdio.h>
的情况使用 printf(),编译器会向我们抱怨(扔一个错误给你)。
我如何知道我需要为 printf() 添加头文件 #include <stdio.h>? 这个答案可以文档里找到。如果你使用 Linux/Unix 系统,man 3 printf
它会在手册页的顶部告诉你需要哪些头文件。
下一行是 main()。 这是 main() 函数的定义; 大括号 {
和 }
之间的所有内容都是函数定义的一部分。
main 函数在很多方面都是一个特殊的函数,它是程序开始执行时将自动调用的函数。在 main() 之前,你的任何东西都不会被调用。
一旦程序执行到 main() 的末尾,也就是在大括号的结尾处,程序就会退出,你会回到命令提示符下。
所以现在我们知道程序引入一个头文件 stdio.h,并声明了一个将在程序启动时执行的 main() 函数。
让我们接下来看看 main 函数内部有什么,在 main 函数内部您向函数 printf() 传递一个参数,这是调用它时要打印的字符串。
字符串中的大多字符将像存储时一样打印出来。 但是有些字符无法在屏幕很好地打印,但它们都使用反斜杠进行转义。最流行的一个是 \n(读作“反斜杠-N”或简称为“换行符”),它对应的是一个换行符,就像在行尾按回车键。
最后将代码复制到 hello.c 文件。 并在类 Unix 平台(例如 Linux、BSD、Mac 或 WSL)上构建,您将从终端使用运行命令 gcc -o hello hello.c
构建 hello.c 文件:
gcc -o hello hello.c
这意味着编译 hello.c
文件并生成可执行程序 hello
。编译完成后,你的当前目录存在 hello
文件,你可以运行命令 ./hello
执行该程序。
./hello
前导 ./
告诉 Shell 从当前目录运行。你将会看到在终端屏幕打印 Hello, World!。
Hello, World!
编译
让我们看看如何构建 C 程序,以及幕后发生的事情。编译是将 C 源码转换为操作系统可以执行的程序的过程。
JavaScript 和 Python 则没有编译步骤,因为它在幕后进行编译, Python 允许您将源码编译成 Python 虚拟机可以执行的字节码。Java 开发者则需要编译程序,这将为 Java 虚拟机生成字节码。
在编译 C 时,会生成机器码。 这是 CPU 可以直接快速执行的 1 和 0。通常不需要编译的语言称为解释语言,也称为脚本。
正如我们上面所说的,gcc 是许多类 Unix 操作系统的编译器。你通常在终端运行 gcc 命令构建 C 语言程序。
Gcc 编译
如果你的当前目录有一个 hello.c
文件,你可以运行命令 gcc -o hello hello.c
编译 hello.c
。
gcc -o hello hello.c
gcc 的 -o
选项指定输出的文件,最后的 hello.c
你想要编译的文件。
如果您的源代码被分成多个文件,您可以将所有 .c
文件放在命令行将它们全部编译在一起,就像它们是一个文件,但规则实际上比单个文件更复杂:
gcc -o awesomegame ui.c characters.c npc.c items.c
并且它们将一起构建成一个更大的可执行文件。这足以你应付多数场景, 稍后我们将讨论多个源文件、目标文件和各种有趣内容。
Clang 编译
在 Mac,标准编译器不是 gcc,而是 clang。但是它还安装了一个封装器,因此你仍然可以运行 gcc 编译源码文件。
您也可以使用 Homebrew 或其他方式安装 gcc 编译器。
IDE 构建
如果您使用的是集成开发环境 (IDE),则不必从命令行构建。在 Visual Studio 快捷键 CTRL-F7
即可构建, CTRL-F5
构建并运行程序。
在 VS Code,您可以按 F5 使用调试器构建并运行。但您必须安装 C/C++ 扩展并正确配置 c 语言项目。
在 XCode,您可以使用快捷键 COMMAND-B
构建,COMMAND-R
运行。要获取命令行工具,请在 Google 搜索 XCode 命令行工具 ,然后您会找到安装它们的说明。
对于入门,通常不建议使用重量级的IDE,例如 XCode ,Visual Studio,你可以选择VS Code 或者 命令行。这对于你深入理解才会有帮助。
C 语言版本
多年来,C 已经取得了长足的进步,它有许多命名的版本号来描述您正在使用的语言的版本。
C 语言的版本使用年份进行规范。最著名的是 C89、C99、C11 和 C2x。在教程中,我们将重点关注后者。
您可以通过指定 Gcc 的 -std=
选项强制 GCC 使用这些版本之一。如果您希望你源码仅支持指定的版本,请添加 Gcc 的 -pedantic
选项。
例如:
gcc -std=c11 -pedantic foo.c
在本教程中,编译的程序都是使用的 c语言 C2x 版本并且打开所有警告。
gcc -Wall -Wextra -std=c2x -pedantic foo.c