一、C程序结构解析
#include <stdio.h>
int main(void)/*一个简单的C程序*/
{
int num;/*定义一个名为num的变量*/
num = 1;/*为num赋一个值*/
printf("I am a simple ");/*使用printf()函数*/
printf("computer.\n");
printf("My favirite number is %d because it is first.\n",num);
return 0;
}
该程序输出结果是:
I am a simple computer。
My favirite number is 1 because it is first.
二、C程序案例详细解析
1、#include <stdio.h> ←包含另一个文件
该行告诉编译器把stdio.h包含在当前程序中,作用相当于把stdio.h文件中的所有的内容都输入该行所在的位置
实际上,这是一种“复制-粘贴”的操作,include文件提供了一种方便的途径共享许多程序共有的信息
- stdio.h:该文件名的含义是标准输入/输出头文件,是C语言编辑器软件包的标准部分,所有C语言编辑器软件包都包含该文件
该文件中包含了供编译器使用的输入和输出函数信息,提供键盘输入和屏幕输出支持
有些程序要包含stdio.h,而有些不用
- #include:这行代码是一条C预处理器指令
通常,C语言编译器在编译前会对源代码做一些准备,即预处理
- 头文件:在C程序顶部的信息集合被称为头文件
大多数情况下,头文件包含了编译器创建 最终可执行程序要用到的信息
- 为什么不内置输入和输出:
a. 并非所有的程序都会用到I/O(输入/输出)包,轻装上阵体现了C语言的哲学
b. #include中的#符号表示,C预处理器是在编译器接手之前处理这条指令
2、int main(void) ←函数名
C程序包含一个或者多个函数,它们是C程序的基本模块
- main():表明该函数名为main
是一个极其普通的名称,但是是唯一的选择
C程序一定是从main()函数开始执行(目前不考虑其他特殊情况)
圆括号用于识别main()是一个函数
- int:是main()函数的返回类型
这表明main()函数返回的值是整数
- void:表明main()函数中不带有如何参数
通常函数名后面的圆括号中包含一些传入函数的信息,该示例中没有传递任何信息,所以圆括号内的单词是void
3、/*一个简单的C程序*/ ←注释
在程序中被/**/两个符号看起来的部分内容是注释
注释可以提高程序的可读性,能够让他人(包括自己)更明白程序
注释只是为了帮助读者理解程序,编译器会忽略它们
C语言注释的好处之一就是,可以将注释放在任何地方,可以与解释的内容放在同一行,较长的注释也可以单独一行,甚至可以占用多行
- 正确的注释:
a./*这是一条注释*/
b./*这也是
一条注释*/
c./*
这还是一条注释
*/
- 错误的注释:
a./*这不是注释
b.这也是不是注释 */
c.这还不是注释
因为它们都缺少标记,所以是一条无效注释
- 原代码:
/* 希望可以运行 */ x=100; y=200; /*其他内容已省略*/
接下来,假设删除第4行,却不小心删除了第三行,现代码:
/*
希望可以运行
y=200;
/*其他内容已省略*/
现在,编译器把等1行的/*和第4行的*/配对,导致4行代码全成了注释。
- C99新增了一种注释//,普遍应用于C++和Java,仅限于单行
//这种注释只能写成一行
x=100;//这种注释也可以置于此
4、{
int num; ←花括号、函数体和块
}
- {:函数体的开始
- }:函数体的结束
所有的C函数必须用花括号{}标记函数体的开始与结束,且只能是花括号{}
- int num;:函数体
- {
int num; :块
}
花括号{}可以将函数中的多条语句合并6一个单元或者块
5、int num; ←声明
这行代码叫做声明
表示在函数中有一个num的变量
int表明num是一个整数
- int:是C语言中的一个关键词,表明一种基本的C语言数据类型
- 关键词:是语言定义的单词
不能用在其他用途,例如,不能用int作为函数名或者变量名
- num:是一个标识符
- 标识符:就是一个变量、函数或者实体的名称
- 声明的作用:将标识符与计算机内存中的特定位置联系起来,同时也确定了存储在某位置的信息类型和数据类型
在C语言中,所有的变量必须先声明才能使用,这意味着必须列出程序中用到的所有变量名及其类型
以前的C语言,还要求将变量声明在块的顶部,其他语句不能在任何声明前面
现在的C99和C11,可以将变量放在块的任何位置,但尽管如此,首次使用变量前,也一定要先声明它
- 数据类型
- 命名:给变量命名时,要使用有意义的变量名或者标识符
如果变量名无法清楚的表达自身的用途,可以在注释中进一步详细说明
可以使用小写字母、大写字母、数字和下划线(_)来命名,但是名称的的一个字符不能是数字
C语言的名称区分大小写
目前编译器只识别63个字符,对于外部标识符,只允许使用31个字符
- 声明变量的4个理由:
a.把所有的变量放在一起,方便读者查找和理解程序用途
b.声明变量会促使你在编写程序之前做一些计划
c.声明变量有助于发现隐藏在程序中的小错误
d.如果事先未声明变量,C程序将无法通过编译
6、num = 1; ←赋值
赋值表达式语句,把值1赋给变量num
该赋值表达式语句从右侧把值赋到了左边
在执行int num:声明时,编译器在计算机内存中为变量num预留了空间,然后在执行赋值表达语句时,把值储存在之前预留的位置
可以给num赋不同的值,这就是num之所以称为变量的原因
7、printf() ←函数
- printf("I am a simple ");
圆括号()表明printf是一个函数名
圆括号()里的内容是main()函数传递给printf()函数的信息(I am a simple )
该消息被称之为参数,更准确来说是函数的实际参数
在C语言中如何调用函数,只需要输入函数名,把所需要的参数填入圆括号即可
当运行这一行时,控制权被转给已命名的函数,函数执行结束以后,控制权被返回至主调函数
- \n:换行,\n组合代表一个换行符
换行符是一个转义序列
- 转义序列:用于代表难以表示或者无法输入的字符
每个转义序列豆一反斜杠字符(\)开始
\t=Tab键、\b=backspace健
- %d:相当于一个占位符,其作用是指明输出num值的位置
%提醒程序,要在该处打印一个变量
d表示要把变量作为十进制整数打印
8、return 0; ←return语句
int main(void)中的int表明main()函数应返回一个整数,有返回值的C函数要有return语句
该句以return为关键字开始,后面是待返回的值,并以分号结尾
如果遗漏return语句,程序在运行最外面的右花括号(})时会返回0
三、简单的程序结构
四、提高程序的可读性
- 写注释
- 选择有意义的函数名
- 在函数中用空行分隔概念上的多个部分
例如,用空行 把声明部分和其他部分区分开来
- 每条语句各占一行
这不是C语言的要求,C语言的格式比较自由,可以将多条语句放在一行,也可以每条语句单独一行
五、进一步使用C
//fathm_ft.c--把两英寻转换为英尺
#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;
}
该程序输出结果是:
There are 12 feet in 2 fathoms!
Yes,I said 12 feet!
1、int feet, fathoms; ←多条声明
程序在一条声明中声明了两个变量,为此要在声明中用逗号将两个声明隔开
2、feet = 6 * fathoms; ←乘法
用*表示乘法
查找变量fathoms的值,用6乘以该值,并把计算结果赋给变量
3、printf("There are %d feet in %d fathoms! \n",feet,fathoms); ←打印多个值
待输出的变量列于双引号后面,变量用逗号隔开
六、多个函数
/* two_fun.c--一个文件包含两个函数*/
#include <stdio.h>
void butler(void);/*ANSI/ISO C函数原型*/
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");
}
该程序输出结果是:
I will summon the butler function.
You rang, sir?
Yes. Bring me some tea and writeable DVDs.
1、void butler(void)
void:第一个void表示butler()函数原型没有返回值(通常,被调函数会向主函数返回一个值),第二个void表示butler()函数不带参数
void在这里的意思是”空的“,而不是”无效“
2、butler()
该函数在程序中被调用3次:
第一次是函数原型,也称之为函数声明,告知编译器在程序中要使用该函数
第二次是以函数调用的形式出现在main()中
第三次是出现函数定义中,函数定义即是函数本身的原代码
3、函数原型:也称之为函数声明,是先调用函数,再定义函数
在main()函数中调用butler()函数
只需要写出”butler()“即可
当butler()执行完成,就会继续执行main()函数的下一条语句
何时执行butler()函数取决于butler()函数在main()函数中被调用的位置,而不是butler()函数的定义在文件中的位置
即使,把butler()函数的定义放在main()函数的定义的前面,也不会变更程序的执行位置
但是,C的惯例还是将main()函数放在开头,因为它提供了程序的基本框架
void butler(void)
{
printf("You rang, sir?\n"); ←函数的定义
}
形式和main()函数相同,都包含了函数头和函数体
函数头重复了函数原型的信息
没有返回值,所以没有return 0;
七、调试程序
1、语法错误
C语言的语法错误指的是,把有效的C符号放在了错误的地方
例如:错写、漏写和多写
main()的函数体应该使用花括号,却使用了圆括号
2、语义错误
C语言的语义错误指的是,错误的意思
因为这类错误没有违反C语言的规则,所以编译器无法检测语义错误
编译器无法理解你的真正的意图,所以你只能自己找到这些错误
例如:n3 = n2 *n2
假设已知n3原意表示为n的3次方,但是这里n3被设置成了n的4次方
3、程序的状态
- 程序状态:是在程序执行过程中,某个定点上所有变量值的集合,它是计算机当前一个状态的快照
通过逐步跟踪程序的执行步骤,并记录每个变量,便可以监视程序的状态
监视程序状态可以帮助我们定位语义错误
- 跟踪程序状态的方法
a. 自己模拟计算机逐步执行程序,当代码中有1000次循环时,可以仅跟踪一小部分循环
在程序的关键点插入额外的printf()语句,以监视变量值的变化,对程序的执行满意后再删除额外的printf()函数
b. 使用调试器,调试器是一种程序,让你一步一步运行另一个程序,并检查该程序变量的值
八、关键字和保留标识符
关键词是C语言的词汇,它们对于C语言而言比较特殊,不能用它们作为标识符
auto | extern | short | while |
break | float | signed | _Alignas |
case | for | sizeof | _Alignof |
char | goto | static | _Atomic |
const | if | struct | _Bool |
continue | inline | switch | _Complex |
default | int | typedef | _Generic |
do | long | union | _Imaginary |
double | register | unsigned | _Noreturn |
else | restrict | void | _Static_assert |
enum | return | volatile | _Thread_local |