因为是初始C语言,所以本文讲的东西很简单,重在认识哈!
1.函数
1.1函数是什么?
函数是一段可重复使用的代码块,用于执行特定的任务或操作。它接受输入(参数)并返回输出结果。函数可以帮助我们组织和模块化代码,使得代码更加可读、可维护和可重用。
在编程中,函数通常由函数名、参数列表、函数体和返回值组成。当函数被调用时,传递给函数的参数值会被传递到函数体中进行处理,并且函数可能会返回一个计算后的结果。
举个栗子:
int Max(int x, int y)
{
if (x > y)
return x;
else
return y;
}
int main()
{
printf("请输入比较的两个数字:");
int num1 = 0;
int num2 = 0;
scanf("%d %d", &num1, &num2);
int max = Max(num1, num2);
printf("最大值为:%d\n", max);
return 0;
}
1.2C语言中函数的分类
1.2.1库函数
C语言中的库函数是预先编写好的可供开发者使用的函数集合。这些库函数提供了各种常见的功能和操作,如字符串处理、数学运算、文件操作等等。
C语言标准库(C Standard Library)是C语言的核心库,提供了一组基本的函数和类型定义。它包含在C语言的编译器中,并且可以通过包含相应的头文件来使用。
以下是一些常用的C标准库函数:
<stdio.h>
:提供了输入输出相关的函数,如printf
、scanf
、fopen
、fclose
等。<stdlib.h>
:提供了内存分配、类型转换、随机数生成等函数,如malloc
、free
、atoi
、rand
等。<string.h>
:提供了字符串处理相关的函数,如strlen
、strcpy
、strcmp
等。<math.h>
:提供了数学运算相关的函数,如sqrt
、sin
、cos
等。<time.h>
:提供了时间和日期相关的函数,如time
、ctime
、strftime
等。
除了C标准库之外,还有许多其他的库函数可供使用。例如:
<ctype.h>
:提供了字符分类和转换相关的函数,如isalpha
、isdigit
、toupper
等。<stdbool.h>
:定义了bool
类型和true
、false
的值。<assert.h>
:提供了断言宏函数,用于调试和错误处理。
此外,还有许多其他的库函数,如网络编程库、图形界面库、数据库访问库等,可以根据具体的需求使用。
1.2.2自定义函数
在C语言中,我们可以通过定义自定义函数来实现特定的功能。自定义函数允许我们将一段代码逻辑封装在一个函数体中,以便在程序的其他地方多次调用。以下是定义和使用自定义函数的一般步骤:
-
函数声明:在使用函数之前,需要提前声明函数的原型。函数原型包括函数名、参数列表和返回类型。这样编译器就能够识别函数的名称和参数。
-
函数定义:在程序的某个地方,编写函数的具体实现。函数定义包括函数头和函数体。函数头包括函数名、参数列表和返回类型。函数体包含函数要执行的代码逻辑。
-
函数调用:通过函数名和参数列表来调用函数。当调用函数时,实参会传递给形参,函数体中的代码会被执行。
以下是一个简单的示例,展示了如何定义和使用自定义函数来计算两个数的和:
#include <stdio.h>
// 函数声明,函数定义
int add_numbers(int a, int b)
{
int sum = a + b;
return sum;
}
int main()
{
int num1 = 2;
int num2 = 3;
// 函数调用
int result = add_numbers(num1, num2);
printf("Sum: %d\n", result);
return 0;
}
在这个例子中,我们首先声明了函数 add_numbers
,它接受两个 int
类型的参数,并返回一个 int
类型的值。然后在 main
函数中,我们定义了两个变量 num1
和 num2
,并将它们作为参数传递给 add_numbers
函数。最后,函数返回的结果被存储在 result
变量中,并通过 printf
函数输出。
通过自定义函数,我们可以将复杂的任务分解成更小的、可重用的代码块,使程序更加模块化和易于理解。
1.3函数的参数
1.3.1实际参数(实参)
在函数调用中,实际参数(Actual Argument)是指在函数调用时传递给函数的实际值。当我们调用函数时,我们可以将具体的数值、表达式、变量等作为实际参数传递给函数。
在前面提到的例子中,我们可以将 num1和 num2作为实际参数传递给 add_numbers
函数。
1.3.2形式参数(形参)
形式参数是指函数名后括号中的变量,因为形式参数只有在函数被调用的过程中才实例化(分配内
存单元),所以叫形式参数。形式参数当函数调用完成之后就自动销毁了。因此形式参数只在函数
中有效。
上面add_numbers
函数中的参数a和b就是形式参数。
2.数组
2.1数组定义
定义:一组相同类型元素的集合。
//定义一个整形数组,最多放10个元素
int arr[10] = {1,2,3,4,5,6,7,8,9,10};
2.2数组的下标
数组的每个元素都有一个下标,下标是从0开始的。
数组是可以通过下标来访问的,但是数组的大小不能用变量指定。
int arr[10] = {0};
//如果数组10个元素,下标的范围是0-9
2.3数组的使用
int main()
{
int i = 0;
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
while (i < 10)
{
printf("%d ", arr[i]);
i++;
}
return 0;
}
3.操作符
3.1算术操作符
+(加) -(减) *(乘) /(除) %(取模)
重点讲一下除法(/)和取模(%)
除法:
- 计算的结果是整除之后得到的商。
- 除法又分为整数除法和浮点数除法,浮点数除法要保证除数和被除数中至少有一个是浮点数。
取模:
- 得到的是余数,只适用于整数。
3.2移位操作符
移位操作符移动的是二进制位。
>>(右移) <<(左移)
<< 左移 -- 移动后,右边插入0以补充空位
>> 右移 --移动后,左边插入0以补充空位
3.3位操作符
& ^ | ~
& 与 --左右操作数,相同位都为1,操作结果该位才为1
| 或 --左右操作数,相同位有一个为1,操作结果就为1
~ 非 --只有一个操作数,对操作数每一位都取反
^ 异或 --左右操作数,对应的位不相同时,操作结果为1
3.4赋值操作符
= += -= *= /= &= ^= |= >>= <<=
3.5单目操作符
! | 逻辑反操作 |
- | 负值 |
+ | 正值 |
& | 取地址 |
sizeof | 操作数的类型长度(以字节为单位) |
~ | 对一个数的二进制位取反 |
-- | 前置,后置-- |
++ | 前置,后置++ |
* | 简介访问操作符(解引用操作符) |
(类型) | 强制类型转换 |
注:前置++(先++后使用)后置++(先使用后++);前置-- 后置-- 一样。
举个栗子:
3.6关系操作符
> | 大于 |
>= | 大于等于 |
< | 小于 |
<= | 小于等于 |
!= | 用于测试不相等 |
== | 用于测试相等 |
3.7逻辑操作符
&& | 逻辑与(并且) |
|| | 逻辑或(或者) |
逻辑与(&&):两个操作数同真为真,一假即假
逻辑或(||):两个操作数一真为真,同假为假
3.8条件操作符
exp1 ? exp2 : exp3 |
exp1为真exp2执行,exp3不执行
exp2为真exp2不执行,exp3执行
int main()
{
int num1 = 10;
int num2 = 19;
int max = (num1 > num2) ? num1 : num2;
printf("%d\n", max);
return 0;
}
3.9逗号表达式
exp1,exp2,exp3,....expN |
从左向右依次计算,逗号表达式的结果是最后一个表达式的结果
int main()
{
int a = 1;
int b = 3;
int c = 5;
int end = (a =3 , c= b + c,c-a);
//a=3,c=5+3,c-a->8-3=5
printf("%d",end);//end =5
return 0;
}
3.10下标引用、函数调用和结构体成员
[] | 下标引用 |
() | 函数调用 |
. -> | 结构成员 |
4.常见关键字
循环 | break,continue,do while,for |
分支 | break,switch,case,default,if else,go to |
数据 | char,int,double,float,long,short |
修饰 | const,signed,unsigned |
下面举几个栗子
4.1关键字typedef
typedef顾名思义是类型定义,理解为类型重命名。
比如
//将unsigned int重名为unit_32
typedef unsigned int unit_32;
int main()
{
unsigned int num1 = 0;
unit_32 num2 = 0;
return 0;
}
4.2关键字static
在C语言中:
static是用来修饰变量和函数的
- 修饰局部变量-称为静态局部变量
- 修饰全局变量-称为静态全局变量
- 修饰函数-称为静态函数
4.2.1修饰局部变量
//代码1
#include <stdio.h>
void test()
{
int i = 0;
i++;
printf("%d ", i);
}
int main()
{
int i = 0;
for(i=0; i<10; i++)
{
test();
}
return 0;
}
//代码2
#include <stdio.h>
void test()
{
//static修饰局部变量
static int i = 0;
i++;
printf("%d ", i);
}
int main()
{
int i = 0;
for(i=0; i<10; i++)
{
test();
}
return 0;
}
对比代码1和代码2的效果理解static修饰局部变量的意义。
结论:
static修饰局部变量改变了变量的生命周期
让静态局部变量出了作用域依然存在,到程序结束,生命周期才结束。
4.2.2修饰全局变量
//代码1
//add.c
int g_val = 2018;
//test.c
int main()
{
printf("%d\n", g_val);
return 0;
}
//代码2
//add.c
static int g_val = 2018;
//test.c
int main()
{
printf("%d\n", g_val);
return 0;
}
代码1正常,代码2在编译的时候会出现连接性错误。
结论:
一个全局变量被static修饰,使得这个全局变量只能在本源文件内使用,不能在其他源文件内使
用。
4.2.3修饰函数
//代码1
//add.c
int Add(int x, int y)
{
return x+y;
}
//test.c
int main()
{
printf("%d\n", Add(2, 3));
return 0;
}
//代码2
//add.c
static int Add(int x, int y)
{
return x+y;
}
//test.c
int main()
{
printf("%d\n", Add(2, 3));
return 0;
}
代码1正常,代码2在编译的时候会出现连接性错误.
结论:
一个函数被static修饰,使得这个函数只能在本源文件内使用,不能在其他源文件内使用。
5.#define定义常量和宏
//define定义标识符常量
#define MAX 1000
//define定义宏
#define ADD(x, y) ((x)+(y))
#include <stdio.h>
int main()
{
int sum = ADD(2, 3);
printf("sum = %d\n", sum);
sum = 10*ADD(2, 3);
printf("sum = %d\n", sum);
return 0;
}
6.结构体
- 在实际应用中,我们通常需要由不同类型的数据来构成一个整体,比如学生这个整体可以由姓名、年龄、身高等数据构成,这些数据都具有不同的类型,姓名可以是字符串类型,年龄可以是整型,身高可以是浮点型。
- 为此,C语言专门提供了一种构造类型来解决上述问题,这就是结构体,它允许内部的元素是不同类型的。
结构体内部的元素,也就是组成成分,我们一般称为"成员"。
结构体的一般定义形式为:
struct 结构体名
{
类型名1 成员名1;
类型名2 成员名2;
类型名3 成员名3;
....
类型名N 成员名N;
};
举个栗子
struct Stu
{
char name[20];//名字
int age; //年龄
char sex[5]; //性别
char id[15]; //学号
};
结构体的初始化
//打印结构体信息
struct Stu s = {"张三", 20, "男", "20180101"};
//.为结构成员访问操作符
printf("name = %s age = %d sex = %s id = %s\n", s.name, s.age, s.sex, s.id);
//->操作符
struct Stu *ps = &s;
printf("name = %s age = %d sex = %s id = %s\n", ps->name, ps->age, ps->sex, ps-
>id);
. | 结构体变量.成员 |
-> | 结构体指针->成员 |
因为是初始C语言所以重在熟悉认识,本文写的也简单,如有不对不妥之处欢迎大佬们批评指正!