本文我们将介绍函数、数组、操作符、关键字的补充、#define定义宏。
1.函数的概念:
维基百科中对函数的定义:子程序。
返回值类型 函数名(参数列表)//函数头
{
函数体(函数实现特定功能的过程);//函数体
}
函数头用来标志一个函数代码的开始,这是一个函数的入口,函数头分成返回值类型、函数名称和参数列表3个部分。
函数体位于函数头的下方,由一对大括号括起来,大括号决定了函数体的范围。
void menu() //简易菜单 返回值类型为void的函数没有返回值
{
printf("************************************\n");
printf("**** 1.Add 2.Sub ****\n");
printf("**** 3.Mul 4.Div ****\n");
printf("**** 0.退出 ****\n");
printf("************************************\n");
}
void Add(int x, int y)
{
printf("%d\n", x + y);//实现加法
}
void Sub(int x, int y)
{
printf("%d\n", x - y);//实现减法
}
void Mul(int x, int y)
{
printf("%d\n", x * y);//实现乘法
}
void Div(int x, int y)
{
printf("%d\n", x / y);//实现除法
}
int main()//程序的入口
{
int input = ;//进行初始化
int x = ;
int y = ;
menu();//调用我们简易设计的菜单函数
printf("请选择:>\n");
scanf("%d", &input);//让使用者选择功能
if (input == 1)//选择1,进入加法
{
printf("请输入两个操作数,空格隔开\n");
scanf("%d %d", &x, &y);
Add(x, y);
}
if (input == 2)//选择2,进入减法
{
printf("请输入两个操作数,空格隔开\n");
scanf("%d %d", &x, &y);
Sub(x, y);
}
if (input == 3)//选择3,进入乘法
{
printf("请输入两个操作数,空格隔开\n");
scanf("%d %d", &x, &y);
Mul(x, y);
}
if (input == 4)//选择4,进入除法
{
printf("请输入两个操作数,空格隔开\n");
scanf("%d %d", &x, &y);
Div(x, y);
}
if (input == )//选择0,退出
{
printf("已退出程序\n");
}
return ;
}
我们来解释一下这段代码:首先我们给出了五个自定义函数,分别是menu(菜单)、Add(加法)、Sub(减法)、Mul(乘法)、Div(除法)。即使main函数在代码段的第32行,我们的程序依然也是从main函数开始自上而下的运行,首先我们定义了整形(整数形式 int)变量input、x、y,然后调用了我们的菜单函数menu。
这段代码明显可以优化,因为我们使用的是int(整形),所以无法计算小数,可以更改为float或者double,这个程序被我们使用了一次就结束了,没有使用循环方便我们多次运行,可以使用do...while循环语句搭配switch case判断语句优化。如果读者朋友感兴趣,可以复制代码段自己尝试进行优化(在文章结尾笔者也会附上优化好的代码段)。
函数这个内容也是未来会单独讲解的章节,这里不过多讲解,目的是能让读者朋友了解函数大概的功能。其实读者朋友应该可以发现,加减乘除这么简单的功能为什么要写这么多函数,这不是多此一举吗?
这里笔者来回答一下,如果程序的任务比较简单,全部的代码可以都写在main()函数中。但是,在实际开发中,程序的任务往往比较复杂,如果全部的代码都写在main()函数中,main()函数将非常庞大臃肿,结构复杂,代码重复。自定义函数就是把编程里面需要反复使用、或者具有特定逻辑功能的代码块封装起来(成为一种模块),使得整体编程过程逐步为模块,分而治之。我们可以根据程序的逻辑和任务的分工把代码划分到不同的自定义函数中,main()更关心业务逻辑和处理流程,需要执行具体任务的时候,调用这些自定义的函数就可以了。函数的特点就是简化代码,代码复用。
数组是在程序设计中,为了处理方便,把具有相同类型的若干元素按有序的形式组织起来的一种形式。这些有序排列的同类数据元素的集合称为数组。数组是用于储存多个相同类型数据的集合。
数组说明的一般形式为:类型说明符 数组名[常量表达式],其中类型说明符是任一种基本数据类型或构造数据类型。数组名是用户定义的数组标识符。方括号中的常量表达式表示数据元素的个数,也称为数组的长度。
C语言中给了数组的定义:一组相同类型元素的集合。
数组中的每个元素都有一个序号,这个序号从0开始,而不是从我们熟悉的1开始,称为下标(Index)。
例如上面的int arr[5]={1,2,3,4,5};,个元素1的下标就是0,所以arr[0]=1。
int arr[5];——定义一个长度为5的整形数组
数组的初始化是指,在创建数组的同时给数组的内容一些合理初始值(初始化)。
可以只给部分元素赋值。当{ }中值的个数少于元素个数时,只给前面部分元素赋值。
只能给元素逐个赋值,不能给数组整体赋值。
如给全部元素赋值,那么在定义数组时可以不给出数组长度。
3.数组的使用
在学习过程中,我们经常会使用循环结构将数据放入数组中(也就是为数组元素逐个赋值),然后再使用循环结构输出(也就是依次读取数组元素的值)。
下面我们进行示例:
简单再说一下个for循环,i初始为0,次进入循环arr[0]=(0+1),也就是arr[0]=1,对应的依次直到arr[9]=10为止,因为循环的条件是i<10。所以在第二个循环依次输出时,结果为上图。
这里我们也可以让用户输入(使用scanf):
十、操作符
1.算数操作符:
+ - * / %
2.位移操作符:
符号:<< >>
<< (左移运算符):不论算术移位还是逻辑移位,均将左边的数舍弃,右边空缺位补0(左边丢弃,右边补0)
>>(右移运算符):当进行逻辑移位时,右边位丢弃,左边空缺位补0(右边丢弃,左边补0)
当进行算术移位时,右边位丢弃,左边位补原数的符号位(右边丢弃,左边补符号位)
3.赋值操作符:
4.单目操作符:
示例:
static在c语言中是“静态”的意思,用于在函数中声明“静态变量”用在每一次调用后,该变量并不在函数返回时立即释放,变量中保存的值,可以保留到下一次调用时继续有效。
静态函数只能在声明它的文件中可见,其他文件不能引用该函数。 不同的文件可以使用相同名字的静态函数,互不影响。
在修饰变量的时, static修饰的静态局部变量只执行一次,而且延长了局部变量的生命周期,直到程序运行结束以后才释放。
static修饰全局变量的时,这个全局变量只能在本文件中访问,不能在其它文件中访问,即便是extern外部声明也不可以。
static修饰一个函数,则这个函数的只能在本文件中调用,不能被其他文件调用。static修饰的局部变量存放在全局数据区的静态变量区。
register修饰符暗示编译程序相应的变量将被频繁地使用,如果可能的话,应将其保存在CPU的寄存器中,以加快其存储速度。
但是使用register修饰符有几点限制。
首先,register变量必须是能被CPU所接受的类型。这通常意味着register变量必须是一个单个的值,并且长度应该小于或者等于整型的长度。不过,有些机器的寄存器也能存放浮点数。
其次,因为register变量可能不存放在内存中,所以不能用“&”来获取register变量的地址。
由于寄存器的数量有限,而且某些寄存器只能接受特定类型的数据(如指针和浮点数),因此真正起作用的register修饰符的数目和类型都依赖于运行程序的机器,而任何多余的register修饰符都将被编译程序所忽略。
在某些情况下,把变量保存在寄存器中反而会降低程序的运行速度。因为被占用的寄存器不能再用于其它目的;或者变量被使用的次数不够多,不足以装入和存储变量所带来的额外开销。
早期的C编译程序不会把变量保存在寄存器中,除非你命令它这样做,这时register修饰符是C语言的一种很有价值的补充。关于register关键字,在《C与指针》这一本书的都151页,作者这样说到:“在许多机器上,register变量所产生的代码将比静态内存中的变量和堆栈中的变量所产生的代码执行速度更快。但是这取决于你的环境,许多当前的编译器比程序员更加懂得怎样合理分配寄存器。”
十二、#define定义宏
相信读者朋友们在了解了函数与操作符之后,通过这张图就可以了解到#define定义宏的作用,即使笔者这里没有输出ret的结果,读者朋友们也应该知道ret的结果。
在这里我们补充一下上文提到的优化后的计算器:
void menu() //简易菜单
{
printf("************************************\n");
printf("**** 1.Add 2.Sub ****\n");
printf("**** 3.Mul 4.Div ****\n");
printf("**** 0.退出 ****\n");
printf("************************************\n");
}
void Add(double x, double y)
{
printf("%.2f\n", x + y);//实现加法
}
void Sub(double x, double y)
{
printf("%.2f\n", x - y);//实现减法
}
void Mul(double x, double y)
{
printf("%.2f\n", x * y);//实现乘法
}
void Div(double x, double y)
{
printf("%.2f\n", x / y);//实现除法
}
int main()
{
int input = ; //初始化
double x = 0.0f;
double y = 0.0f;
do //do while循环
{
menu();
printf("请选择:>\n");
scanf("%d", &input);
switch (input)
{
case 1:
printf("请输入两个操作数,空格隔开\n");
scanf("%f %f", &x, &y);
Add(x, y);
break;
case 2:
printf("请输入两个操作数,空格隔开\n");
scanf("%f %f", &x, &y);
Sub(x, y);
break;
case 3:
printf("请输入两个操作数,空格隔开\n");
scanf("%f %f", &x, &y);
Mul(x, y);
break;
case 4:
printf("请输入两个操作数,空格隔开\n");
scanf("%f %f", &x, &y);
Div(x, y);
break;
case :
printf("退出程序\n");
break;
default: //当用户没有选择1-4时进行提示
printf("输入错误\n");
break;
}
} while (input);//只有当while()时停止循环,对应为退出
return ;
}
至此我们已经初步了解函数、数组、操作符、关键字的补充#define定义宏 的大致内容。