跳过正文

丙加·第1章·砸——瓦鲁多!(你好,世界!)

·387 字·2 分钟·

本章讲述一些基础的 C/C++语法。

我们遵循程序界的 优良(?)传统,先展示一个输出“Hello World”的程序。
先是 C 版本(C++基本上 可以理解为 C 的超集,语法略有不同,但是大部分 C 程序可以直接通过编译。差别后面 可能 会介绍)

#include <stdio.h>

// 主函数体,程序就此开始
int main(void) {
    printf("Hello World!\n");

    return 0;
}

然后是 C++版本

#include <iostream>
using namespace std;
// 主函数体,程序就此开始
int main(void) {
    cout << "Hello World" << endl;
    // 如果编译器支持最新的C++草案(C++25),那么有更简单的
    // include 一行修改成 #include <print>
    // 然后 cout 就可以写成 std::println("Hello, world!\n");

    return 0;
}

下面开始解释

  1. #include <stdio.h>#include <iostream>
    这是“包含”(include)语句。stdio.hiostream 中定义了很多基本的输入和输出函数,比如这里使用的 printf()cout。要使用他们,就需要包含他们所在的头文件。 include 是预处理指令,也就是在编译(把代码翻译成机器能理解的二进制形式)环节之前做的工作,所以开头是 #include 文件的目的就是把多个编译单元(也就是 C/C++代码)公用的内容,单独放在一个文件里减少整体代码尺寸。实际的作用就相当于把 include 的头文件复制整合一份在你的代码里面。就像做菜前先把菜谱准备好
    include 的语法是:#include <头文件> 或者 #include "头文件"。一般地,<> 包裹的是标准库中的头文件;而 "" 包裹的是不属于标准库中的文件(比如你自己写的头文件)。当然如果你混用了,大部分编译器也不会产生错误。
    stdio.h 是 C 语言的标准库之一,全称是 Standard Input & Output(标注输入输出),.h 是 C 语言头文件的后缀,Header( 文件),不过 .h 后缀并非必须项。
    iostream 是 C++的标准库之一,全称是 Input & Output Stream(输入输出流)。

    碎碎念

    C++也可以使用 C 语言的库,但是为了避免名称冲突,C++标准规定,C 语言库的头文件如 stdio.h,在 C++中对应的版本是 cstdio,并且其中定义的名称(如 printf)位于 std 命名空间(别急,见下一条)中。 虽然大多数编译器允许直接使用 stdio.h,但使用 cstdio 是更符合 C++标准的做法。比如建议使用 #include <cstdio> 而不使用 #include <stdio.h>,虽然体量较小的项目后者多半能通过编译,但会污染全局命名空间(“全局”就是指不需要 命名空间::标识符,直接访问或者使用 ::标识符 明确指定访问的命名空间)。
    使用 <cstdio> 时,就要记得 std::printf 了。

  2. (C++)using namespace std; C++独有的语句。为了避免名称冲突(比如较大项目中两个人各自定义了相同名字的变量、形式完全相同的函数等等),引入了命名空间的理念。标准库中的函数都在命名空间 std 中,包括以 #include <cstdio> 这种 c 开头的 C 语言兼容库。必须通过 命名空间::标识符 的格式来指定到底是哪一个标识符(标识符简单来说就是变量、函数名的统称),比如 std::cout

    上面的示例直接使用 cout,是因为语句 using namespace std;,这句话告诉编译器,我说的标识符,默认可以从 std 命名空间查找。不过不建议在真正的生产环境这么做,因为大项目容易产生名称冲突;建议养成 std::cout 的习惯。

    碎碎念: 在 3.中提到了污染全局命名空间,这里举一个例子:
    在 stdio.h 中,标识符都位于全局命名空间,其中有一个行输入函数 int puts(const char *str)(名称是“puts”,返回整数,输入一个字符串(指针)的函数)。如果你 不巧 习惯不好也定义了一个 puts,那么现在全局有 2 个 puts。如果这两个 puts 长得不一样(参数列表不一样),在 C++里面那还勉强可以区分(这种区分叫做函数重载;C 年纪大了老眼昏花看不清,会直接报错),但如果这两个外表长得一模一样,就不免上演一出真假美猴王的大戏。当然,编译器不吃瓜,会及时地产生一个 error 叫停。

    题外话: C/C++是大小写敏感的语言,所以关键字、标识符等等必须注意大小写,int varibleA;int VARIBlEa;int function1() { ... }int Function1() { ... },、int 是类型关键字但 INT 如果没有特殊处理不是类型关键字。

  3. int main(void) { ... } 定义了一个返回值为 int(Integer,整数),函数名称为 main(主函数),不接受任何参数(void,空)的函数。 而 {} 标记了函数的开始和结束。
    main 是 C/C++函数开始执行的位置(现阶段暂时这么理解)。程序会依次执行里面的指令,直到达到 } 或者 return 语句(返回,后面会细说) 。
    函数的定义语法是:

    返回类型 函数名(参数类型 参数 1, 参数类型 参数 2, ...) { ... }
    

    如果没有返回值,就用 void 占位置。比如 void func1(int a) { ... }void func2() { ... }。后一个例子参数列表是空的等效于 void
    至于具体有哪些类型、哪些名字是允许、规范的,将在下一章详细阐述。这一章我们先把握整体概念。

    碎碎念: 不像 Python,C/C++其实不依赖缩进(就是一行代码前面带上空白),但是为了美观 以及方便你故地重游,我们习惯上会一个大括号一层缩进
    编辑 C/C++时,缩进一般是 4 个空格,或者一个 Tab,不过有些编辑器会自动统一,将 4 个空格统一成一个 Tab,或者反过来。 强烈建议使用空格进行缩进,并将编辑器设置为将 Tab 键输出为固定数量的空格(通常是 4 个,有些人是 2 个)。这可以保证代码在任何环境和编辑器下看起来都是一致的。

  4. printf("Hello World!\n");cout << "Hello World!" << endl;
    这两个语句都是打印语句。同样会打印 "Hello World!" 然后换行。\nstd::endl 效果上都是换行,但是内部不一样,\n 会快一些。
    C/C++的“语句”都以 英文 分号结束,如果你忘记加了,编译器(或者代码分析器)会在你忘记写分号的 下一行 报错,以 GCC 为例内容大概是:

    xxx.c: In function ‘main’:
    xxx.c:5:5: error: expected ‘;’ before ‘printf’
     5 |     printf("Hello, World!\n");   --> 这是你漏掉分号的下一行,到了这一行编译器才能真正确定你没有打分号
       |     ^~~~~~
    

    意思是你第五行前面没打分号。报错位置是第五行第五个字符(xxx.c:5:5
    顺带一提,// 后面和 /* ... */ 里面的内容表示注释,会被忽略。两者区别在于 // 只管一行,而 /* */ 可以横跨多行

    为什么 '\n' 表示换行?std::endl 又是什么?<< 是什么标识符?怎么输出变量?这些问题你将会在后来的章节得到答案。

  5. return 0; 这是“返回”语句,也就是程序的执行流程归还给上一层调用者,并且给出一个值(这个值叫做“返回值”,类型就是上文 3. 所说的“返回类型”)。这里只有一个函数 main,那返回给谁呢?由于程序由操作系统调用,所以最后当然是返回给系统啦!(其实中间还有很多过程,但是我们暂时选择性眼瞎)
    因此,main 函数统一的返回值都是 int(整形)。void main() { ... } 的形式 可能 会被编译器支持,但这是非标准的形式,所谓“法无禁止皆可为”,好一点的情况是,编译器可能会发出警告,而且默认返回 0;最坏的情况下,编译器会产生完全不可预期的行为。
    一般地,0 表示程序成功执行,没有错误;而其他的值表示程序有不同的状况。至于 main 除了 void 这种空参数列表,还有什么形式?为什么有的程序启动行为每次不一样?你将在未来的学习中了解到这些知识。


这就是一个朴素的 Hello World 程序了。下面找出程序的错误,检验下学习成果吧:

  1. (12 处错误和严重不规范;1 处编码习惯不佳)

    inculde studioh
     INT mian(){
     print("Hello World\n")    /* 打印语句
     }
    
  2. (2 处错误;有两种较好的改法)

    #include <iostream>
    int main() {
        cout << "Hello World" << endl;
    
        return 0;
    

    习题答案另附

    本章我们阅读了第一个 C/C++程序,并理解了基本结构。下一章我们将深入学习变量与数据类型。

命令提示符@CommandPrompt-Wang
作者
命令提示符@CommandPrompt-Wang