本笔记写于2020年1月27日。

本系列文章参考的是《C Primer Plus》(第六版),其中里面会有笔者自己的相关补充。

以下示例均运行于macOS Catalina 10.15.2上,编译器为clang 11.0.0

PS:如果笔记中有任何的错误,请在下方评论中留言,我会及时回复并修改,谢谢

简单的C示例

首先来看一个非常简单的C程序示例

#include <stdio.h>

int main(void)
{
int num;
num = 1; printf("I am a simple ");
printf("computer.\n");
printf("My favorite number is %d because it is first.\n", num); return 0;
}

结果如下:

![ch02_first.c](https://raw.githubusercontent.com/WeiCG/Blog.Picture/master/C/C Primer Plus/ch02/ch02_first.png)

解析

上述示例看似简单,但也基本展示了C程序的方方面面。本节将详细解释其中的每一行代码

#include和头文件

第一行#include <stdio.h>是一条预处理指令。在第一章笔记的最后一幅图中,可以看到编译器将源代码文件编译为了目标文件,而实际上在编译操作执行前,编译器会对源代码文件进行一些处理操作,这些操作被称为预处理。(有关预处理器的更多知识请看第十六章的笔记)

#include语句是一个文件引用的预处理指令,意思是将stdio.h文件中的所有内容复制到#include <stdio.h>的所在区域,实质上是一种“复制-粘贴”的工作。

引用的文件stdio.h则是C语言的标准库文件之一,该文件中包含了C语言常用的输入输出函数,如:示例中使用的printf函数。由于这类文件常常是在C语言代码文件的头部引用,因此也被称为头文件

笔者补充:截止到2020年1月27日,C语言共包含标准库文件29个,其中包括C11标准中新增的5个

![ch02_预处理流程图](https://raw.githubusercontent.com/WeiCG/Blog.Picture/master/C/C Primer Plus/ch02/ch02_预处理流程图.png)

main函数

int main()

C程序包含一个或多个函数,函数是C程序的基本模块。而示例第二行的main()函数,则是C程序的开始函数,所以的C程序都是从main()函数开始的。我们还可以定义很多其他的函数,但main()函数一定是开始函数。程序在执行时首先会寻找main()函数,然后依次执行函数中的语句。

圆括号()表明了main()是一个函数,而不是一个其他什么东西;intmain()函数的返回类型,表明main()函数返回的值是整数;括号中的void表明该函数的参数为空。(有关函数的更多的知识可以查看第九章的笔记)

笔者补充:main函数不一定是C程序的开始函数,只不过绝大部分的C语言编译器都以main()函数作为默认的程序入口点。我们可以通过一定的方法修改C程序的开始函数,如果有时间,笔者会专门写一篇这个笔记来介绍。

注释

上述示例中由于偷懒,笔者没有写注释,这里说一下。

C语言注释共有两种

  • 多行注释:这是C语言原本的注释形式,程序中被/* */符号括起来的部分就是程序的注释
/* 有效的注释 */

/* 分成了两行,
也是有效的注释 */ /*
有效的注释
*/ /* 无效的注释,因为缺少了结束标记
  • 单行注释:C99标准新增,以//开始,在双斜线后面处于同一行的所有内容都是程序的注释
// 有效的注释
int num; // 也可以写在这里

花括号、函数体和块

所有的C函数都使用花括号标记函数的开始和结束,而且,只有花括号({})可以标记,圆括号(())和方括号([])都不行。同时,花括号还可以用于把函数中的多条语句合并为一个单元或块。

声明

声明是C语言最重要的特性之一。示例中的int num;语句是一条声明变量语句,它完成了两个工作:

  1. 在函数中有一个名为num的变量

  2. num变量的类型是int类型,即整数类型

语句末尾的分号表明该语句已经结束,C语言以分号;作为语句结束的标志

关键字和标识符

语句中的int是C语言的关键字,它表示了一种基本数据类型(关于基本数据类型请看第三章笔记)。关键字是语言定义的一种具有特定用途的单词,不能用作其他用途。截止到2020年1月17日,C语言中共包含了44个关键字。

语句中的num是一个标识符,它表示了一个变量、函数或其他实体的名称。通过标识符,程序将计算机内存中的特定位置与一个名称联系起来,也确定了存储在该特定位置的信息类型或数据类型。

标识符有以下需要注意的地方:

  1. 标识符应该要使用有意义的名称,使人望文生义。同时,如果标识符本身无法清楚的表达自身的用途,可以在注释中进行进一步的阐述

  2. 在C语言中,标识符是区分大小写的,也就是说numNum是两个不同的标识符

  3. 标识符中可以包括小写字母、大写字母、数字和下划线,但名称的第一个字符必须是字符或下划线,不能是数字

  4. 不能使用关键字作为标识符,因为关键字已经有了其他用途了。同理,C语言中还存在有一些保留标识符(包括以下划线开头的部分标识符标准库函数名)也不应该作为标识符使用

赋值操作

赋值是C语言的基本操作之一。在介绍标识符中曾提到过,通过标识符,程序将计算机内存中的特定位置与一个名称联系起来。但之前的声明仅仅是告诉编译器要在内存中预留出这块空间来,并将这块空间与对应标识符联系起来,并没有使用这块空间。

赋值操作便是使用空间的一种方法。示例中num = 1;表示将数字1放入变量num对应的预留空间中,同时,还可以对该空间进行多次赋值,因此,num被叫做变量。

关于赋值操作更多的详细内容请看第五章笔记

printf()函数

printf("I am a simple ");
printf("computer.\n");
printf("My favorite number is %d because it is first.\n", num);

首先,圆括号()表明了这是一个函数,printf是这个函数的名称,即函数的标识符。而圆括号中的内容是main()函数传递给printf()函数的信息,被称为函数参数。示例中的printf()函数是C语言的一个标准函数,作用是格式化输出参数信息。

关于printf()函数以及函数参数中的\n%d等更多的信息请查看第四章笔记

return语句

在上面关于main()函数介绍中,曾说”intmain()函数的返回类型,表明main()函数返回的值是整数“。return语句的作用便是返回相应的值。示例的最后一句return 0;表示要返回数字0

C语言规定,有返回值的C函数必须要求return语句,该语句以return关键字开始,后面待返回的值。如果函数不需要返回任何值的话,则需要在对应位置使用void关键字表明该函数不需要返回任何值。

进一步使用C

在看过第一个简单的C程序之后,再看一个更复杂的C程序

// fathm_ft.c -- 把2英寸转换为英尺
# include <stdio.h> int main(void)
{
int feet, fathoms; fathoms = 2;
feet = 6 * fathoms;
printf("There are %d feet in %d fathoms!\n", feet, fathoms);
printf("Yes, I said %d feet!\n", 6 * fathoms); return 0;
}

结果如下:

![ch02_fathm_ft](https://raw.githubusercontent.com/WeiCG/Blog.Picture/master/C/C Primer Plus/ch02/ch02_fathm_ft.png)

解析

示例2-2比起示例2-1来说,变化不大,主要新增了

  1. 声明多个变量。声明多个变量时,变量与变量之间需要使用逗号隔开int feet, fathoms;

  2. 乘法。示例2-2中使用了语句feet = 6 * fathoms;来执行乘法操作,主要意思是将变量fathoms的值乘以6,然后将计算结果赋给变量feet

  3. 打印多个值。在第一条printf()语句中使用了两个替换符,替换符与变量一一对应,变量之间用逗号隔开;第二条printf()语句说明待打印的值可以不是变量,只要是合适类型的变量即可

多个函数的C程序

上面的示例中我们都只编写了main()函数,并在main()函数中调用了的printf()函数,但printf()函数是C语言提供的。在示例2-3中我们将使用自己编写的函数,并在main()函数中完成调用。

// two_func.c -- 一个文件中包含了两个函数
#include <stdio.h> void butler(void); // C99标准的函数原型 int main(void)
{
printf("I will summon the butler function.\n");
butler(); // 函数调用
printf("Yes. Bring me some tea and writeable DVDs.\n"); return 0;
} void butler(void) // 函数定义
{
printf("You rang, sir?\n");
}

运行结果如下:

![ch02_two_func](https://raw.githubusercontent.com/WeiCG/Blog.Picture/master/C/C Primer Plus/ch02/ch02_two_func.png)

解析

在示例2-3中,butler()函数一共出现了三次。

  1. 函数原型,也可以称为函数声明,作用是告知编译器在程序中要使用该函数。在使用函数前,对函数进行声明是非常重要,就像变量一样,如果不进行声明,编译器在编译过程便会报错。同时,函数声明的形式也很重要,要以返回类型 函数名称(函数参数);形式,注意后面的分号不能忘记

  2. 函数调用,示例中在main()函数中调用了butler()函数

  3. 函数定义,函数定义中便是函数本身的源代码

PS:何时执行函数取决于函数在main()中被调用的位置,而不取决于函数定义的位置。即使将bulter()函数定义写在main()函数之前,也不会改变程序的执行顺序,仍然是上面的执行结果

关于函数的更多详细内容请查看第九章笔记

程序中的错误

在编写程序时,很容易就会犯一些错误,程序中出现的错误被称为bugs,而找出并修正错误的过程就叫做debug

程序中出现的错误总结归为以下两类

  1. 语法错误,即不遵循C语言的语法规则。最常见的语法错误就是忘记写分号,C语言规定每条语句结尾都应该有分号,如果忘记写分号,编译器就会报错

  2. 逻辑错误,程序没有得到预期的结果,即程序中出现逻辑上的错误。比如:本来要计算a的3次方,但由于编写程序失误,计算成了a的4次方。这种情况下,程序的语法没有错误,编译器顺利编译运行,但运行后的结果出错

一般来说,编译器可以直接报出语法错误,但对于逻辑错误,编译器便没有办法了,这时候可以使用调试器debugger来协助发现逻辑错误。

笔者

第二章主要的目的是对C程序有一个简单的了解。

从这章中我学到了

  1. C程序由一个或多个函数组成。函数是C程序的基本模块。每个C程序都有一个main()函数,程序从main()函数开始执行

  2. C语句以分号表示结束

  3. 声明是C语言的一个重要特性。在变量和函数使用前,都要进行声明,主要作用是向编译器表明程序中要使用这个变量或函数了

  4. 学会了printf()函数;学习了int关键字,表示整型变量,可以在printf()函数中使用%d输出

《C Primer Plus》- 第二章 C语言概述的更多相关文章

  1. C Primer Plus_第二章_C语言概述_复习题与编程练习

    REVIEW 1.如何称呼C程序的基本模块? ans 它们被称为函数 2.什么是语法错误?给出一个英语例子和一个C语言例子 me C的语法错误是指把正确的C符号放在了错误的位置 likes codin ...

  2. 第二章 c语言概述

    一.#include指令和头文件 1.#include C预处理指令,C编译器在编译前对源代码做一些准备工作 2.stdio.h标准输入输出头文件,提供了关于输入输出的信息供编译器使用 头文件包含了建 ...

  3. 第二章 C语言编程实践

    上章回顾 宏定义特点和注意细节 条件编译特点和主要用处 文件包含的路径查询规则 C语言扩展宏定义的用法 第二章 第二章 C语言编程实践 C语言编程实践 预习检查 异或的运算符是什么 宏定义最主要的特点 ...

  4. 01 C语言程序设计--01 C语言基础--第1章 C语言概述&第2章 GCC和GDB

    走进嵌入式开发的世界,企业级项目课程让你达到企业嵌入式应用开发要求.名师在线答疑,解决疑难.科学评测体系,系统评估学习.核心项目实........ 30 门课程 241小时12分钟 824 人学习 学 ...

  5. 第1章 Java语言概述--HelloWorld--环境搭建

    SE学什么 第1章 Java语言概述 第2章 基本语法 第3章 数组 第4章 面向对象编程(上) 第5章 面向对象编程(中) 第6章 面向对象编程(下) 第7章 异常处理 第8章 枚举类&注解 ...

  6. C#语言————第二章 C#语言快速热身

    第二章    C#语言快速热身 ***********一.选择结构**************** 1:if选择结构与java的if选择结构语法完全相同 2:switch选择结构 ①:常量表达式的值可 ...

  7. javaSE习题 第一章 JAVA语言概述

    转眼就开学了,正式在学校学习SE部分,由于暑假放视频过了一遍,略感觉轻松,今天开始,博客将会记录我的课本习题,主要以文字和代码的形式展现,一是把SE基础加强一下,二是课本中有很多知识是视频中没有的,做 ...

  8. [编程笔记]第一章 C语言概述

    //C语言学习笔记 第一讲 C语言概述 第二讲 基本编程知识 第三讲 运算符和表达式 第四讲 流程控制 第五讲 函数 第六讲 数组 第七讲 指针 第八讲 变量的作用域和存储方式 第九讲 拓展类型 第十 ...

  9. [HeadFirst-JSPServlet学习笔记][第二章:高层概述]

    第二章:高层体系结构 容器 1 什么是容器? servelet没有main()方法.它们受控于另一个Java应用,这个Java应用称为容器(Container) Tomcat就是这样一个容器.Web服 ...

随机推荐

  1. PHP mb_substr mbstring 函数

    定义和用法 mb_substr - 获取部分字符串 版本支持 PHP4 PHP5 PHP7 支持 支持 支持 5.4.8 length 传入 NULL,则从 start 提取到字符串的结尾处. 在之前 ...

  2. 最初步的.NET MvcApi + Vue 前后端分离IIS部署

    一.完成项目,各个项目部署在IIS上 1.前端项目部署     完成项目后在控制台npm run build 生成了dist文件夹 主要是部署这个文件夹 打开IIS  和部署AspNet MVC项目一 ...

  3. 015.CI4框架CodeIgniter数据库操作之:Query带参数查询数

    01.我们在Models中写数据库的操作.具体的查询代码如下: <?php namespace App\Models\System; use CodeIgniter\Model; class U ...

  4. 001.Delphi插件之QPlugins,一个最简单的插件

    安装QPlugins里面的Demo,复制粘贴着写了一个最简单的插件,看看好不好用 EXE代码如下: unit Main_Frm; interface uses Winapi.Windows, Wina ...

  5. NirSoft 实用程序

    64-bit (x64) utilities package 此软件包包含NirSoft中的所有实用程序,这些实用程序具有64位版本(x64)Windows的独立构建. 此程序包包含下面列表中每个实用 ...

  6. idea 将java 项目 打包成jar包

    记录一下,防止忘记.ps : 请忽略这个是web项目 1.idea 打包jar包 (1)首先打开Project Structure,选中Artifacts (2)点击绿色加号,选中jar ,然后选中f ...

  7. v2??? 重启失败

    v2??? 重启失败, 提示 Authorization not available. Check if polkit service is running or see debug message ...

  8. 16 协程和www

    1.一个应用程序一般对应一个进程,一个进程一般有一个主线程,还有若干个辅助线程,线程之间是平行运行的,在线程里面可以开启协程,让程序在特定的时间内运行.2协程和线程的区别是:协程避免了无意义的调度,由 ...

  9. 5分钟搞懂:JWT(Json Web Token)

    https://www.qikegu.com/easy-understanding/892 JWT 基于token的用户认证原理:让用户输入账号和密码,认证通过后获得一个token(令牌),在toke ...

  10. springboot - 使用ErrorAttributes 在我们自定义的 ErrorController中

    1.概览 基于<springboot - 映射 /error 到自定义且实现了ErrorController的Controller>改造,仅将MyCustomErrorController ...