一、程序是如何运行的
我们知道计算机只识别0,1,那么当我们把程序编写完成后,计算机是如何运行这个程序的呢?
在ANSI C的任何一种实现中,存在两种不同的环境,第一种是翻译环境,在这个环境中源代码就会被转换为可执行的机器指令;第二种就是执行环境,它用于实际执行代码。而这两种环境不需要运行在一台机器上。
1. 翻译环境
翻译其实就是程序的编译,这往往有几个步骤组成。
第一步:预处理器阶段处理,在这个阶段预处理器在原代码上执行一些文本操作,如读入头文件,用实际值代替由# define 定义的符号等。
第二步:解析阶段,也是产生绝大多数错误和警告信息的地方,随后就会产生目标代码,目标代码就是机器指令的初步形式。
2. 执行环境
程序的执行也需要经历几个阶段。
第一步:程序载入内存中,在具有操作系统的环境中(宿主环境)由操作系统来将其载入内存,那些不是存储在栈堆中尚未初始化的变量将会在这个时候得到初始值。若是独立环境(即没有操作系统),就需要手动安排。
第二步:开始执行程序(准备工作)。在宿主环境中,通常由一个小型的启动程序和程序链接在一起。接着,调用main函数。
第三步:执行程序。在绝大多数机器中,程序将使用一个运行时的堆栈,用于存储函数的局部变量和返回地址。程序同时可以使用静态内存,存储在静态内存中的变量在程序的整个执行过程中将一直保留它们的值。
第四步:程序的终止。可能有不同原因引起的程序的终止,正常终止就是指main函数 正常返回,也有可能因为执行过程中的错误自行中断。
二、hello world(实例代码的运行)
1. 编写代码
代码如下(示例):
#include <stdio.h>
int main()
{
printf("hello world");
}
<stdio.h> 是一个标准输入输出的头文件,在我们的代码中的输出printf ,所以必须引用这个头文件。每个程序必须有一个主函数,也就是main函数,程序的运行顺序主要由main函数中的代码自上而下运行的。最终的printf语句就是一个标准输出语句,格式就是printf("输出内容"); ,需注意每个语句都必须以分号结尾,表示一个语句的结束。
其次为了代码的可读性,我们往往会在代码中增添注释,可以使用// 进行单行注释,或者使用/* 开头和*/ 结尾来进行多行注释。
三、数据类型
在c语言中有4中基本数据类型:整型,浮点型,指针和聚合类型。其中指针和聚合类型我们下一次在具体看这部分的内容。
整型中包括字符,短整型,整型和长整型,其中短整型至少16位,长整型至少32位,缺省的整型往往由编译器决定其是16位还是32位,通常是该机器最自然高效的位数。字符型在本质上是一种小整型,缺省的char要么是signed char要么是unsigned char 这往往也取决于编译器,所以,只有当程序中所使用的char值位于这两种字符型的交集中,才能具有良好的可移植性。(或者,我们为了拥有良好的可移植性,可以显性的定义为signed char或者unsigned char,但这往往会收机器兼容性等的影响,使得这种统一显性的声明并非是上上之策)。
浮点型包括float,double,long double 类型,通常这些类型分别提供单精度、双精度和某些支持扩展精度的机器上提供扩展精度,所以的浮点类型必须能容纳从10^-37 到10^37 之间的任意数。
#include <stdio.h>
int main() {
printf("%c\n",'a');
printf("%d\n",123);
printf("%f\n",3.14);
return 0;
}
四、运算符
程序中数字之间是可以像数学中数字一样进行运算的。 如下:
#include <stdio.h>
int main() {
printf("%d\n",1+2+3);
return 0;
}
常用的简单运算有算术运算符、关系运算符和逻辑运算符三类运算符。
类型 | 常用符号 | 注意 |
---|
算术运算符 | + 、 - 、 * 、 / 、 % | %指的是取余操作 | 移位运算符 | 左移为<< ; 右移为>> | 汇编语言中常用,知识将一个值的位向左移或向右移。 | 位操作符 | 与:& 或:| 异或 ^ | | 赋值 | = | 赋值同时还是一个表达式,赋值表达式的值就是左操作数的新值 | 复合赋值符 | += -= *+ /= %= <<= >>= &= ^= |= | 以+= 为例,a+=b 其实就是 a=a+b,这种写法主要是使得代码更加紧凑。 | 单目操作符 | ++、 – 、 &(取地址)、 sizeof(判断操作数的类型长度) | 这里需要特别注意的是++ 和-- ,在a++ 这个表达式中隐含两个值,一个是变量a本身的值,一个是表达式a++的值,在后缀和前缀这两种表达中,变量的值都会发生改变,但只有当其为前缀时表达式的值为变量改变后的值。 | 关系操作符 | > >= < <= != == | 需注意这些操作符产生的结果都是一个整型值,而不是一个布尔值,所以他可以赋值给一个变量。符合这个关系式的值为1,不符合为0 | 逻辑操作符 | && || | 用于对表达式求值,由于这种操作符具有短路操作,所以必须保证表达式的顺序正确。 | 条件操作符 | 如(a>5)?b-6:c/2 | 代替了if-else ,意义是指,a>5成立时计算b-6否则计算c/2 |
五、控制语句
if-else
if(条件){
}else{
}
也可以直接省略else,有以下代码块;
if(条件){
}
或者多分枝选择结构还可以使用如下:
if(条件1){
} else if(条件2){
} else if(条件3){
}else{
}
switch-case
switch(表达式){
case 整型常量1:
break;
case 整型常量2:
break;
default :
}
while循环
while(条件){
}
do-while语句
do {
}while(条件);
do-while循环与while循环的区别: do-while循环是先循环后判断,循环体至少执行一次;while循环是先判断后循环,循环体可能一次也不执行。
for 循环
for (初始值;条件;递增或递减){
}
在while和for循环中,break是结束整个循环体;continue是结束单次循环。
练习:打印出一个九九乘法表。
#include <stdio.h>
int main(){
for(int i=1;i<10;i++)
{
for(int j=1;j<=i;j++)
{
printf("%d*%d=%d ",i,j,i*j);
if(i*j<10)
printf(" ");
}
printf("\n");
}
|