前言
- C语言------顾名思义是一种语言,也就是我们通常所说的交流方式。不过这与我们日常生活中所使用的语言并不完全相同,C语言主要是给编程人员来使用的,它存在的目的是能让程序员更为便捷的与计算机进行交流。我们都知道,计算机只能识别二进制的机器指令,但C语言代码写完后是类似于字符构成的文本文件,其以.exe为后缀生成可执行程序。这也就意味着,在这个过程中一旦进行运行就需要编译器的参与,它可以将我们书写出的代码翻译成计算机可以识别的指令。
一、什么是C语言?
- C语言是一门通用的计算机编程语言 (计算机编程语言又被简称为计算机语言,它是人和计算机交流的语言,目前已知的计算机语言已经有上千种,而当下所介绍的C语言只是其中的一种),其广泛应用于底层开发 (所谓底层即操作系统及以下部分:诸如操作系统,驱动等。当然,这并不代表C语言无法应用于上层软件开发,例如早期的QQ就是用C语言编写的。)
- 如上图所示(电脑中各个层之间的工作关系)。如果我们购买了一台新电脑,一开始是无法使用的,只有当你在电脑中装上了操作系统之后才可以正常使用。这个时候,我们就可以在操作系统之上安装各式各样的应用软件了。当然了,在我们的电脑和操作系统之间是有一层驱动层的,驱动层横跨操作系统和电脑,操作系统调用驱动来驱动我们的硬件来进行工作。
- C语言的设计目标是提供一种能以简易的方式编译、处理低级存储器(为了实现对硬件的直接操作和底层的控制)、产生少量的机器码(机器码指的是将硬件序列号经过一系列加密、散列形成的一串序列号)以及不需要任何运行环境支持便能运行的编程语言。 尽管C语言提供了许多低级处理的功能,但仍然保持着良好的跨平台特性,以一个标准规格写出的C语言程序可在许多电脑平台上进行编译,甚至包含一些嵌入式处理器(单片机或称MCU)以及超级电脑等作业平台。
- 二十世纪八十年代**,为了避免各开发厂商所用的C语言语法产生差异,由美国国家标准局为C语言制定了一套完整的**美国国家标准语法,称为ANSI C,作为C语言最初的标准。 [1] 目前2011年12月8日,国际标准化组织(ISO)和国际电工委员会(IEC)发布的C11标准是C语言的第三个官方标准---C89,C99,C11),也是C语言的最新标准(其中C89和C90应用的比较广泛,外加少许的C99标准内容),该标准更好的支持了汉字函数名和汉字标识符,在一定程度上实现了汉字编程。
- C语言是一门面向过程的计算机编程语言 ,与C++,Java 等面向对象的编程语言有所不同。 其编译器主要有Clang(苹果开发)、GCC(Linux操作系统下)、WIN-TC、SUBLIME、MSVC(vs)、Turbo C等。
二、为什么要学习C语言?
- 在计算机的发展史上并非从一开始就有高级语言,而是先从二进制编写代码开始的,后续才逐渐衍生出由助记符等帮助记忆的字符书写的汇编代码--->B语言--->最后才出现C语言/C++/JAVA/Python等。
我们时常听到"C语言是编程之本","C生万物"这些话并不是空穴来风,正如C++是完全兼容C并在C语言的基础上加以改进的一样,我们JAVA的底层也是由C语言写的,Linux操作系统,Android系统的内核也都是用C语言编写的。
就以上数据看来,IT行业中C语言的排名一直居高不下,不仅仅是因为使用广泛,或许更是因为C语言是人机交互最接近底层的桥梁,能更好地帮助我们理解编程的思想。
- 那么介绍到目前为止,我想我们已经初步了解到了C语言的概念以及在使用C语言时可以为我们带来的便利。尽管在编程的过程中,编程语言只是其中的冰山一角,但这可以为我们后续学习更为深入的知识奠定好夯实的基础。
- C语言作为众多编程语言的一种,仍旧在编程排行榜中霸占着前几的位置,这就足以说明使用的广泛程度。如果我们想要真正了解它的语法规则和编码方式,还是需要使用最为直接的方式------也就是代码来给大家进行后续的展示。当然了,学习其他语言的小伙伴们也不要过于担心,当我们熟悉了某一种编程语言之后,等到后续再去接触其他编程语言时都会变得更加轻松高效,触类旁通。
三、第一个C语言程序
3.1 写程序前的准备工作
- 上面我们已经提到了C语言写出来的代码是需要编译器或者是IDE(集成开发环境)来转换成计算机能够识别的二进制指令。大家按照自己的喜好选择适合自己的编译器就可以的。
- 当我们打开自己安装好的IDE之后,如果想要正式开始书写第一个C语言程序,首先需要在编译器中创建一个新的项目(这个时候请注意,项目最好起个有意义的名字,请勿使用中文或者特殊字符及空格等,以免出现意想不到的错误)。当项目创建完成之后,就可以在解决方案资源管理方案中创建属于自己的.c文件(源文件)了。当然,请注意将自己的源文件代码按照自己的方式存储管理起来,注意事项与项目一致。
3.2 代码示例(一)
c
#include<stdio.h>
//stdio--standard input and output.标准输入输出头文件
//在使用输入输出库函数时需要包含该头文件
int main(void)
//void 写到这里表示的是main函数不需要参数
//main()即主函数,是程序的执行入口,一个工程内可以包含多个.c文件。但多个.c文件中有且只能有一个主函数
{
printf("hello,world!\n");
//printf是专门用于在屏幕上打印的库函数,可指定输出格式
return 0;
//return 0表示正常返回,与代码前方的int相互呼应
}
输出结果如下图所示:
3.2 代码示例(二)
c
#include <stdio.h>
int main()
{
printf("%d\n", 100);
//%d是指在屏幕上以10进制的形式打印出一个整型数值
printf("helloworld\n");
//正常输出:helloworld
printf("hello\nworld\n");
//\n是一个特殊的转义字符表示:换行。
//所以打印出的效果是:
//hello
//world
return 0;
}
输出结果如下图所示:
四、数据类型
4.1 数据类型概况
- char
字符数据类型,输出时可选用%c进行打印。
- short
短整型数据类型,输出时可选用%hd进行打印。
- int
整型数据类型,输出时可选用%d进行打印。
- long
长整型数据类型,输出时可选用%ld进行打印
- long long(C99中引入的数据类型)
长整型数据类型,输出时可选用%lld进行打印。
- float
精度浮点数,输出时可选用%f进行打印。
- double
双精度浮点数,输出时可选用%lf进行打印。
4.2 数据类型的作用
在C语言中,数据类型的了解是为了方便我们后续根据需要创建需要变量,以解决生活中的问题。
c
#include <stdio.h>
int main()
{
char ch = 'w';
//变量的创建方式:数据类型+变量名 = 初始值;
int age = 20;
//数据类型的主要作用是用来创建变量的,并且我们一般会在创建时顺道给它赋上初始值。
float salary = 10000.0f;
//后面的f表示:该数据是一个float类型的数据,负责编译器会将他默认为double类型的数据
double weight = 45.5;
printf("%d\n",age);
//%d这个格式表示的是在屏幕上打印一个10进制的整数,\n表示换行
printf("%f\n",salary);
//打印float类型的数据时要使用%d。输出时屏幕上默认在小数点后打印六位
printf("%.1f\n",salary);
//小数点后的位数可以通过控制输出的格式来指定
printf("%lf\n",weight);
//打印double类型的数据时要使用%ld。输出时屏幕上默认在小数点后打印六位
return 0;
}
输出结果如下图所示:
- 小贴士:C语言的便捷性很大程度上与他的数据类型众多有关,当然C语言中也有众多的操作符可以为我们提供便捷操作。在上面我们简单的介绍了在C语言中各个数据类型该如何创建变量以及为何会出现这么多的数据类型,那么接下来我们就要了解一下各个数据类型的大小,以便未来我们可以根据大小来申请空间创建变量。
4.3 计算机的存储单位
C语言中的存储单位有:Bit ,Byte,KB,MB,GB,TB,PB等 1Byte = 8 Bit; 1KB = 1024 Byte; 1MB = 1024 KB; 1GB = 1024 MB ; 1TB = 1024 GB; 1PB = 1024 TB;
· 既然我们已经大概了解了各个单位之间的转换,那么接下来就让我们学习一下如何计算数据类型的长度。(示例如下)
4.4计算数据类型所占的空间大小
c
#include <stdio.h>
int main()
{
printf("%d\n",sizeof(char));
//sizeof是一个操作符,单位是字节。其专门用于计算数据类型或是变量的大小
printf("%d\n",sizeof(short));
printf("%d\n",sizeof(int)); //4个字节
printf("%d\n",sizeof(long)); //4个字节 或者 8个字节
//(请注意:C语言中规定,sizeof(long)>= sizeof(int)即可)
printf("%d\n",sizeof(long long)); //8个字节
printf("%d\n",sizeof(float)); //4个字节
printf("%d\n", sizeof(double)); //8个字节
return 0;
}
4.5 总结小贴士
1. C语言中没有字符串数据类型,但可以使用字符数组对一组系统类型的元素进行连续存放,并使用%s进行输出打印。 2. C语言中出现诸多数据类型是为了让程序员在进行程序设计时,选用最为恰当的类型进行变量的创建,尽量少的占用内存空间去存储这些变量。
五、变量
5.1在C语言中为什么要有变量?
既然上面已经说过了,数据类型主要是用来创建变量的,那么现在我们就来简单认识一下变量。 在我们的日常生活中有些值是可变的(身高,年龄,体重,工资......),有些值是永恒不变的(血型,性别.......)。那么既然C语言要解决生活中的问题,那么必须有能力去产生这样的数据,所以在C语言中,与之相对应的两个概念就是变量和常量。
- 好的,既然大家有了初步的概念之后,我们接下来就先来介绍一下变量。
5.2 变量的创建方式
变量的创建方式:数据类型 变量名 = 赋值。 eg:int age = 18;
- //创建整形变量并进行初始化,如果局部变量没有初始化就进行打印,编译器会报错,显示"使用了未初始化的局部变量"。如果是全局变量没有初始化的话,默认值为0。
5.3变量的命名规则
- 变量名只能由字母(包括大写和小写),数字,下划线(-)组成 。但要格外注意的是:变量名绝对不能由数字开头,否则编译器会报错。
- 变量名长度不能超过63个字符,太长了容易紊乱。
- 变量名中严格区分大小写 eg:int age = 0;与int Age = 0。这两个实例中的age和Age是两个完全不同的变量。
- **当然,还有一点需要着重注意:变量名不能使用C语言预先设定好的关键字。C语言内置的32个关键字下面将在本文的第十三节附图提供给大家参考(图源网络)。
:
5.4变量的分类
1.全局变量:定义在全局范围内的变量叫做全局变量 。 2.局部变量:定义在局部范围内的变量叫做局部变量。
5.4.1 局部变量的使用
代码示例(一)
c
#include <stdio.h>
int main()
{
int a = 10;
//在局部范围内的变量被称为局部变量
//局部变量的适用范围是该变量所在的局部范围,生命周期是从变量的创建到变量的销毁这整段时间
printf("%d\n", a);
/*
{
int a = 10;
}
printf("%d\n",a);//这个时候的a不在范围内所以编译器会报错
*/
return 0;
}
输出结果如下图所示:
代码示例(二)
c
#include <stdio.h>
int main()
{
//int a = 10;
//在局部范围内的变量被称为局部变量
//局部变量的适用范围是该变量所在的局部范围,生命周期是从变量的创建到变量的销毁这整段时间
//printf("%d\n", a);
{
int a = 10;
}
printf("%d\n",a);//这个时候的a不在范围内所以编译器会报错
return 0;
}
输出结果如下图所示:
5.4.2 全局变量的使用
代码示例(一)
c
#include <stdio.h>
int a = 10;
//不在局部范围内,而在全局范围内的变量就是全局变量
//全局变量的适用范围是整个项目,生命周期也是整个main函数的生命周期
//如果全局变量是在其他源文件中定义的,此时只需要使用extern 关键字申明外部符号即可正常使用
int main()
{
printf("%d\n", a);
return 0;
}
输出结果如下图所示:
代码示例(二)
使用其他源文件中全局变量的正确使用方式:
代码示例(三)
使用其他源文件中全局变量的错误使用方式:
5.5 学后思考
- 说到目前为止,我相信大家对于全局变量和局部变量的适用范围已经有了初步的了解,那么接下来我们要开始学习一下当局部变量和全局变量名字冲突时会产生什么样的反应呢?是编译器报错,亦或是正常输出某个值呢?
c
#include <stdio.h>
int global = 2019;
//全局变量
int main()
{
int local = 2018;
int global = 2020;
//局部变量
printf("%d\n",global);
//当局部变量与全局变量名字冲突时,局部变量优先
return 0;
}
输出结果如下图所示:
- 小贴士:从这个示例中,我们可以得出一个最为准确的答案:当局部变量和全局变量名字冲突时,编译器并不会报错而是会遵循就近原则输出答案。有局部变量使用局部变量,有全局变量使用全局变量。
5.6 变量的作用域与生命周期
1.作用域(scope)是程序设计概念,通常来说,一段程序代码中所用到的名字并不总是有效或是可用的,而限定这个名字的可用性的代码范围就是这个名字的作用域。 2.局部变量的作用域是该局部变量所处的局部范围,全局变量的作用域是整个工程 3.变量的生命周期指的是变量的创建到变量的销毁之间的一个时间段 4.局部变量的生命周期是进入作用域生命周期开始,出了作用域生命周期结束。全局变量的生命周期是整个工程的生命周期
代码示例(一)
c
#include <stdio.h>
int g_a;//声明全局变量,如果后续没有给他赋值,这里默认输出值为0。
void test()
{
printf("2:test:%d\n", g_a);;
}
int g_a = 2022;
//编译器的扫描是自上而下的,如果我们是在后面才定义这个符号,编译器会报错。
//这也就是为什么在第三行要定义变量了。先定义后使用,是为了防止编译器报错。
int main()
{
printf("1:test:%d\n", g_a);;
test();//函数调用
return 0;
}
输出结果如下图所示:
错误代码示例(二)
c
#include <stdio.h>
//int g_a;
//声明全局变量,如果后续没有给他赋值,这里默认输出值为0。
void test()
{
printf("2:test:%d\n", g_a);;
}
int g_a = 2022;
//编译器的扫描是自上而下的,如果我们是在后面才定义这个符号,编译器会报错。
//这也就是为什么在第三行要定义变量了。先定义后使用,是为了防止编译器报错。
int main()
{
printf("1:test:%d\n", g_a);
test();//函数调用
return 0;
}
输出结果如下图所示:
改进代码示例(三)
c
#include <stdio.h>
int g_a = 2022;
//定义也是一种声明。
//全局变量的作用域是整个工程
void test()
{
printf("2:test:%d\n", g_a);
}
int main()
{
printf("1:test:%d\n", g_a);
test();//调用函数
return 0;
}
输出结果如下图所示:
5.7 学后测试
介绍到目前为止,相信大家对于变量已经有了进一步的思考,那么接下来就让我们自己来尝试一下利用C语言写一段功能代码。
c
#include <stdio.h>
int main()
{
int num1 = 0;
int num2 = 0;
int sum = 0;
printf("请输入两个操作数:>");
scanf("%d %d",&num1,&num2);
//从键盘中读取数据需要取出变量地址后进行存放
sum = num1 + num2;
printf("%d\n",sum);
return 0;
}
输出结果如下图所示:
六、常量
6.1 常量的分类
arduino
好的。到目前为止我们已经大概了解了变量以及变量的部分内容,接下来我们要继续进入常量的学习。
在C语言中常量可大致分为以下几类:字面常量、const修饰的常变量、#define定义的标识符常量、枚举常量。
6.2 字面常量
6.2.1 什么是字面常量
所谓字面常量就是直接在代码中敲出来的,可以直接看出答案的常量。例如字符常量,整型常量字面值,
浮点数类型字面值等,都可以划分到这一块。
6.2.2 代码演示
c
#include <stdio.h>
int main()
{
'w';
//字符类型字面值
"abcdef";
//字符串类型字面值
3.14;
//浮点数类型字面值
1000;
//整形类型字面值
}
6.2.3 总结小贴士
- 这个是很简单的概念,唯一需要注意的就是,在代码中不能出现中文的符号,否则编译器报错。
6.3 const修饰的常变量
6.3.1 什么是常变量?
1.变量之所以被称之为变量,是因为变量的值是可变的。那么在C语言中有没有特殊情况呢?答案是:有的。 2.C语言中有一个叫做const的关键字,被const修饰的变量,虽然在本质上仍然是一个变量,但它因为const的作用,导致该变量在语法层面上被赋予了常量属性,这就导致了后续无法直接对这个变量进行修改。
6.3.2 正常变量代码示例
c
#include <stdio.h>
//int g_a;
//声明全局变量,如果后续没有给他赋值,这里默认输出值为0。
#include <stdio.h>
int main()
{
int num = 10;
printf("%d\n", num);
num = 20;
printf("%d\n", num);
return 0;
}
输出结果如下图所示:
6.3.2 代码示例(一)
c
#include <stdio.h>
int main()
{
const int num = 0;
num = 20;
// 此时代码会报错
return 0;
}
输出结果如下图所示:
6.3.3 代码示例(二)
c
#include <stdio.h>
int main()
{
//int arr[10] = { 0 };//这是整型数组的正常定义形式
//下面我们来测试一下被const修饰之后的变量是否还是变量
int n = 10;
int arr[n] = { 0 };
//在不支持C99的编译器下不可以使用变长数组,即不可使用const修饰的变量来指定数组大小
//但在支持C99的编译器下使用变长数组时依旧不可以初始化。所以第八行这句代码一定是错的
return 0;
}
输出结果如下图所示:
6.3.4 总结小贴士
- 综上述两个简单代码中,我们完全可以检测到之前所说的"被const修饰的变量,虽然在本质上仍然是一个变量。"这句话的真实性。可千万不要把它误认为一个常量哦。
6.4 #define定义常量和宏
6.4.1 #define定义常量代码示例
c
#include <stdio.h>
#define M 100
int main()
{
int arr[M] = { 0 };//此时的M是常量
printf("%d\n", M);
return 0;
}
输出结果如下图所示:
6.4.1 #define定义常量代码错误示例
c
#include <stdio.h>
#define MAX 100
int main()
{
MAX = 200;
printf("%d\n", MAX);//错误原因:MAX是常量标识符
return 0;
}
输出结果如下图所示:
6.4.2 #define定义宏代码示例
c
#include<stdio.h>
#define MAX(x,y) (x > y ? x : y)
//MAX的参数x和y分别被下面的a,b所替代,所以就变成了MAX(a,b) (a > b ? a : b)
int main()
{
int a = 0;
int b = 0;
scanf("%d %d", &a, &b);
int m = MAX(a, b);
//int m = (x > y ? x : y);
printf("%d\n", m);
return 0;
}
输出结果如下图所示:
6.5 枚举常量
6.5.1 什么是枚举常量?
枚举类型是一种自定义的数据类型,并不是C语言中内置的数据类型。它可以定义一组命名的常量集合。每个枚举常量都代表一个特定值,这些值可以用于程序中的各种场景。** 枚举常量的关键字是enum,枚举常量值的命名一般用大写字母,这样可以与其他变量和函数的命名区分开。
6.5.2 枚举常量默认赋值代码演示(一)
c
#include <stdio.h>
enum Sex
{
//枚举类型enum Sex的可能取值,他们都是枚举常量
MALE,
FEMALE,
SECRET
};
//定义枚举类型时,内部为枚举常量,常量的默认值为0,在创建时可以同时赋值
int main()
{
enum Sex s1 = MALE;
enum Sex s2 = FEMALE;
enum Sex s3 = SECRET;
printf("s1 = %d\n", s1);
printf("s2 = %d\n", s2);
printf("s3 = %d\n", s3);
return 0;
}
输出结果如下图所示:
6.5.2 枚举常量默认赋值代码演示(二)
c
#include <stdio.h>
enum Color
{
RED,
GREEN,
BLUE
};
int main()
{
enum color c = BLUE;//颜色这种枚举类型所创建的变量
printf("RED = %d\n", RED);//0
printf("GREEN = %d\n", GREEN);//1
printf("BLUE = %d\n", BLUE);//2
printf("c = %d\n", BLUE);//2
return 0;
}
输出结果如下图所示:
总结小贴士: 从上述2个代码示例中,我们可以清晰的观察到一个规律:如果枚举类型中的枚举常量没有被初始化,那么枚举常量默认从0开始打印并逐渐递增。
6.5.3 枚举常量赋值演示代码(一)
c
#include <stdio.h>
enum SEX
{
MALE = 4,
FEMALE,
SECRET
};
//枚举常量虽然在后面无法被修改,但是我们可以根据需要再创建变量的时候赋初始值
int main()
{
enum SEX s1 = MALE;
enum SEX s2 = FEMALE;
enum SEX s3 = SECRET;
printf("%d\n", s1);//4
printf("%d\n", s2);//5
printf("%d\n", s3);//6
return 0;
}
输出结果如下图所示:
6.5.3 枚举常量赋值演示代码(二)
c
#include <stdio.h>
enum SEX
{
MALE ,
FEMALE = 4,
SECRET
};
//枚举常量虽然在后面无法被修改,但是我们可以根据需要再创建变量的时候赋初始值
int main()
{
enum SEX s1 = MALE;
enum SEX s2 = FEMALE;
enum SEX s3 = SECRET;
printf("s1 = %d\n", s1);//0
printf("s2 = %d\n", s2);//4
printf("s3 = %d\n", s3);//5
return 0;
}
输出结果如下图所示:
6.5.3 枚举常量赋值演示代码(三)
c
#include <stdio.h>
enum SEX
{
MALE ,
FEMALE,
SECRET = 4
};
//枚举常量虽然在后面无法被修改,但是我们可以根据需要再创建变量的时候赋初始值
int main()
{
enum SEX s1 = MALE;
enum SEX s2 = FEMALE;
enum SEX s3 = SECRET;
printf("s1 = %d\n", s1);//0
printf("s2 = %d\n", s2);//1
printf("s3 = %d\n", s3);//5
return 0;
}
输出结果如下图所示:
6.5.3 枚举常量赋值错误代码演示
c
#include <stdio.h>
enum SEX
{
MALE ,
FEMALE,
SECRET
};
//枚举常量虽然在后面无法被修改,但是我们可以根据需要再创建变量的时候赋初始值
int main()
{
MALE = 3 ;//错误代码
enum SEX s1 = MALE;
enum SEX s2 = FEMALE;
enum SEX s3 = SECRET;
printf("s1 = %d\n", s1);//0
printf("s2 = %d\n", s2);//1
printf("s3 = %d\n", s3);//5
return 0;
}
输出结果如下图所示:
总结小贴士: 从上述4个代码示例中,我们可以清晰的观察到一个规律:如果枚举类型中的枚举常量被初始化了,那么后续枚举常量将不支持被修改,并且从被开始赋值的枚举常量开始,如果后面有枚举常量,那么常量按照赋值+1继续递增,前面没有赋值的枚举常量依旧从0开始逐渐递增。
七、字符串
7.1什么是字符串?
我们在敲代码的时候都是从键盘中输入各种各样的字符,单个字符用' '引起即可。但如果是要存储多个字符,这个时候我们就要引入字符串的概念了。 那么什么是字符串呢?其实,在C语言中,由双引号引起来的一串字符就被称为字符串字面值,简称字符串。例如:"abcdef","a",""(空字符串)等。
7.2 字符串打印代码测试
c
#include <stdio.h>
int main()
{
char ch1[4] = "abc";
char ch2[3] = { 'a','b','c' };
char ch3[4] = { 'a','b','c','\0' };
printf("%s\n", ch1);
printf("%s\n", ch2);
printf("%s\n", ch3);
//%s时用来打印字符串的,数组名是数组首元素的地址,交付之后会自主往后打印,直到打印到\0为止
return 0;
}
好的,接下来我们来调试起来这个代码,看一下字符数组中是如何存放这些字符的。
7.2.1学后思考:
在这里,我们可以发现一个神奇的现象:
虽然字符数组ch1中我们只放进了字符串abc用以初始化,但在内存中ch1数组不仅显示放入了字符串"abc",还在末尾隐藏存放了一个\0。但在ch2数组我们只是单纯使用多个字符初始化数组,所以内存中只正常显示原本存入的字符,那么这又会导致什么样的效果呢?如果我们主动在字符串的后面放上\0,ch3数组的打印效果会和ch1数组一致吗?
接下来我们来揭晓一下结果。 输出结果如下图所示:
7.2.2 学后反思
现在我们可以从以上代码得出一个结论:当我们在使用%s打印数组的时候,会从数组的首元素的地址开始向后打印,直至打印到\0为止,这也就是为什么ch2数组在打印完"abc"后还会出现其他字符,这是因为我们无法判断内存中其他地方存放的究竟是什么内容。但当我们在字符数组中主动放入\0后,%s打印出的结果就会和ch1数组一致了。
7.3 计算字符串个数代码测试
c
#include <stdio.h>
#include <string.h>
int main()
{
char arr1[13] = "hello world!";
char arr2[5] = { 'a','b','c','d' };
char arr3[4] = "abcd";
//字符串后默认存放了一个\0
char arr4[5] = { 'a','b','c','d','\0' };
printf("%d\n", strlen(arr1));
//strlen是专门用来计算字符串的长度的库函数,所以需要包含头文件#include <string.h>
printf("%d\n", strlen(arr2));
printf("%d\n", strlen(arr3));
printf("%d\n", strlen(arr4));
//strlen函数求的是字符串中\0之前的字符的个数
return 0;
}
内存中是这么存储三个数组的,所以才会在打印数组以及计算数组个数时产生不同的效果。
输出结果如下图所示:
7.4 计算字符串长度代码测试
c
#include <stdio.h>
#include <string.h>
int main()
{
char ch1[4] = "abc";
//以字符串的形式初始化数组ch1,内存中该数组内真实存储的内容其实是"abc\0"。所以打印结果是3
char ch2[3] = { 'a','b','c' };
char ch3[4] = { 'a','b','c','\0' };
//原理如ch1所示
int len1 = strlen(ch1);
int len2 = strlen(ch2);
int len3 = strlen(ch3);
printf("%d\n", len1); //3
printf("%d\n", len2); //随机值
//这里出现随机值的原因是:在这个字符数组中,内存中仅仅存储了'a','b','c'三个字符,我们无法
//判断\0究竟什么时候出现,但strlen求的是字符串的个数,字符串的结束标志是\0,所以我们无法猜
//测到具体打印出的数字是多少
printf("%d\n", len3); //3
return 0;
}
输出结果如下图所示:
总结小贴士: 从以上代码我们可以得出一个结论:字符串的结束标志是一个 \0 的转义字符,但是在计算字符串长度的时候 \0 是结束标志,并不算作字符串的内容。计算的其实是\0之前出现的字符的个数。
7.5转义字符
7.5.1 什么是转义字符?
转义字符是一种在计算机编程中使用的特殊字符序列,用于表示一些特殊的字符或控制字符。 :::
7.5.2转义字符有哪些?
7.5.3转义字符的使用效果
所谓转义字符就是将字符原本的意义进行转变,转义字符是一个字符。
c
#include <stdio.h>
int main()
{
printf("\a");//电脑响铃
printf("abcd\bef\n");
printf("(are you ok??)\n");//are you ok]
printf("(are you ok\?\?)\n");//are you ok?
printf("%c\n",'\'');
printf("%s\n","\"");
printf("abcndef\n");
printf("abc\ndef\n");
printf("%s\n","\\n");
printf("c:\test\test.c\n");
printf("c:\\test\\test.c\n");
printf("abcd\refg\n");//\r回车
printf("abcd\vefg\n");//\垂直制表符
printf("abcd\fefg\n");//\f进纸符
printf("%c\n",'\121');
//注意八进制的数只有0-7;
//1*8^2+2*8^1+1*8^0=81,ASCII码值对应的字符就是即将要打印的字符
printf("%c\n",'\x27');
//2*16^1+7*16^0=39,ASCII码值对应的字符就是即将要打印的字符
return 0;
}
输出结果如下图所示:
7.5.4 ASCII码对照表(图源网络)
7.6 注释
1.在C语言中起先是使用/**/来注释项目中不再需要的代码或者是注释给自己看的内容,但是这种方式的缺点是:无法嵌套使用。编译器在扫描到注释时会自动屏蔽,所以不用担心乱码出现。 2.由于C语言中原本的注释方式有缺陷,所以后续C中也可以支持C++的屏蔽方式:// 3.编译器中屏蔽代码的快捷方式:Ctrl + k + c;取消注释的方式:Ctrl + k + u。
八、选择语句
8.1 什么是选择语句
在我们的生活中处处面临着选择,于是在C语言中就引入了分支的概念。 选择语句是编程中用于根据特定条件执行不同代码块的语句。常见的选择语句有两种:if语句和switch语句。
8.2 什么是if语句
if语句是C语言分支语句中的一种常见方式,if语句用于根据条件执行不同的代码块。如果条件为真(非零),则执行代码块1;否则执行代码块2。如果条件为真,还可以使用if语句的延续形式,这种形式允许根据多个条件执行不同的代码块。
8.2.1 if语句代码测试用例
c
#include <stdio.h>
int main()
{
int n = 0;
printf("明天需要早起上早八吗?(0/1):>");
scanf("%d", &n);//1
if (1 == n)
{
printf("明天需要上早八。\n");
}
else if (0 == n)
{
printf("明天不需要早起上早八。\n");
}
else
{
printf("抱歉,输入错误。\n");
}
// if ... else 是一句代码。进入if语句之后将不再进入else语句
return 0;
}
输出结果如下图所示:
8.3 什么是Switch语句
switch语句是C语言分支语句中的一种常见方式,switch语句用于根据不同的条件执行不同的代码块。switch语句根据表达式的值与每个case标签的值进行比较,如果匹配,则执行相应的代码块。如果没有匹配的case标签,则执行default代码块(可选)。每个case标签后面都有一个break语句,用于结束switch语句的执行,防止继续执行下一个case的代码块。
8.3.1Switch 语句代码测试用例(正确版本)
c
#include <stdio.h>
int main()
{
int day = 0;
scanf("%d", &day);//3
switch (day)
{
case 1:
printf("星期一\n");
break;
case 2:
printf("星期二\n");
break;
case 3:
printf("星期三\n");
break;
case 4:
printf("星期四\n");
break;
case 5:
printf("星期五\n");
break;
case 6:
printf("星期六\n");
break;
case 7:
printf("星期天\n");
break;
default:
printf("抱歉,输入错误。\n");
break;
}
return 0;
}
输出结果如下图所示:
8.3.2Switch 语句代码测试用例(错误版本)
c
#include <stdio.h>
int main()
{
int day = 0;
scanf("%d", &day);//3
switch (day)
{
case 1:
printf("星期一\n");
break;
case 2:
printf("星期二\n");
break;
case 3:
printf("星期三\n");
case 4:
printf("星期四\n");
case 5:
printf("星期五\n");
case 6:
printf("星期六\n");
break;
case 7:
printf("星期天\n");
break;
default:
printf("抱歉,输入错误。\n");
break;
}
return 0;
}
输出结果如下图所示:
8.3.3 学后反思
在Switch语句中case标签代表执行入口,而break标签则表示执行出口,所以在书写break语句时,如果需要结束一定要加上break语句,防止后续遗漏导致代码错误。
九、循环语句
9.1 什么是循环语句?
在生活中我们经常面临着重复性的事情,于是在C语言中就引入了循环的概念。 循环语句是指在编程语言中用于重复执行某段代码块的语句结构。它会在条件满足的情况下,不断地执行代码块,直到条件不再满足为止。 在许多编程语言中,包括 Python、Java、C++ 等,都有循环语句的实现。根据条件检查的位置,循环可以分为两种类型:前测试循环和后测试循环。在C语言中,最常见用于循环语句的有 for 循环和 while 循环,do while循环较少使用。
9.2 while 循环代码测试用例
学习小贴士:
- while 循环是后测试循环的代表,它会先执行代码块,然后再检查条件,如果条件满足,就继续执行代码块,直到条件不再满足。
c
#include <stdio.h>
int main()
{
int line = 1;
while (line <= 20000)
{
printf("%d:仍要继续努力敲代码。\n", line);
line++;
}
if (line > 20000)
{
printf("可以去看一场电影了。\n");
}
return 0;
}
输出结果如下图所示:
9.2.1break跳出while 循环代码测试用例
c
#include <stdio.h>
int main()
{
int line = 1;
while (line <= 20000)
{
printf("%d:仍要继续努力敲代码。\n", line);
line++;
if (line == 500)
{
printf("我陷入爱河了。\n");
break;
}
}
if (line > 20000)
{
printf("可以去看一场电影了。\n");
}
return 0;
}
输出结果如下图所示:
9.2.2continue 跳出while 循环代码测试用例
c
#include <stdio.h>
int main()
{
int line = 1;
while (line <= 20)
{
printf("%d:仍要继续努力敲代码。\n", line);
line++;
if (line == 5)
{
printf("过年了,今天暂时不写代码了。\n");
continue;
}
}
if (line > 20)
{
printf("可以去看一场电影了。\n");
}
return 0;
}
输出结果如下图所示:
9.3 for 循环代码测试用例
学习小贴士:
- for 循环是前测试循环的代表,它会先检查条件,如果条件满足,就执行代码块,然后继续检查条件,直到条件不再满足。
c
#include <stdio.h>
int main()
{
int i = 0;
int sum = 0;
for(i = 1 ; i <= 10 ; i++)
{
sum += i;
}
printf("sum = %d\n",sum);
return 0;
}
输出结果如下图所示:
9.3.1break跳出for循环代码测试用例
c
#include <stdio.h>
int main()
{
int i = 0;
int sum = 0;
for(i = 1 ; i <= 10 ; i++)
{
sum += i;
if(i == 2)
break;
}
printf("sum = %d\n",sum);//3
return 0;
}
输出结果如下图所示:
9.3.3continue 跳出 for 循环代码测试用例
c
#include <stdio.h>
int main()
{
int i = 0;
int sum = 0;
for(i = 1 ; i <= 10 ; i++)
{
if(i == 2)
continue;//跳出本次循环,不将2 累加,直接将2 自增为3再累加
sum += i;
}
printf("sum = %d\n",sum);
return 0;
}
输出结果如下图所示:
9.4 do...while 循环代码测试用例
学习小贴士: do...while 循环是 while 循环的变体。在检查while条件是否为真之前,该循环首先会执行一次do之内的语句,然后在while内检查条件是否为真,如果条件为真的话,就会重复do...while这个循环,直至while为假。
c
#include <stdio.h>
void menu()
{
printf("**********************\n");
printf("********1.play********\n");
printf("********0.exit********\n");
printf("**********************\n");
}
int main()
{
int input = 0;
do{
menu();
printf("请问是否需要进入游戏?(0/1):");
scanf("%d", &input);
if (1 == input)
{
printf("玩儿游戏。\n");
}
else
{
printf("退出游戏。\n");
break;
}
}while (input);
return 0;
}
输出结果如下图所示:
9.5 循环语句学习总结
在循环中,我们通常需要使用 break 和 continue 语句来控制循环的流程。break 语句会直接结束整个循环,而 continue 语句则会跳过当前循环的剩余部分,直接进入下一次循环。(具体示例代码我们将在后续进行介绍)
十、函数
10.1 什么是函数?
在C语言中,函数是一组被命名的语句集合,用于执行特定的任务。函数可以接受输入参数,执行一定的操作,然后返回结果。C语言中的函数包括库函数和用户自定义函数两种。 函数的概念包括以下几个要点: 1.函数头:函数的声明或定义由返回类型、函数名以及参数列表组成。返回类型指定了函数返回值的类型,函数名是用来唯---标识函数的名称,参数列表包含了传递给函数的数据。 2.函数体:函数的具体实现部分,包括一系列语句和表达式。函数体中的语句将按照顺序执行,以完成特定的任务。 3.参数传递:函数可以接受输入参数,通过参数列表传递数据给函数。参数可以是基本数据类型(如整型、浮点型等)或指针类型。通过参数传递数据,可以在函数内部使用这些数据。 4.返回值:函数可以返回一个值作为函数执行后的结果,返回值的类型必须与函数头中的返回类型相匹配。如果函数没有返回值,可以用void作为返回类型。
10.2 函数代码示范用例
10.2.1 函数求和代码示例
c
#include <stdio.h>
int Add(int x, int y)
{
/* int z = x + y;
return z;
*/
return (x + y);
}
int main()
{
int num1 = 0;
int num2 = 0;
printf("请输入两个操作数:>");
scanf("%d %d", &num1, &num2);
int sum = Add(num1, num2);
//函数的特点是简化代码,代码复用
printf("sum = %d\n", sum);
return 0;
}
输出结果如下图所示:
10.2.2 scanf函数的返回值示例代码(一)
c
#include <stdio.h>
int main()
{
int a = 0;
int ret = scanf("%d",&a);
//如果读取正常的话,返回的是读取到的数据的个数
printf("ret = %d\n",ret);// 1
printf("a = %d\n",a); //输入值
return 0;
}
输出结果如下图所示:
10.2.3 scanf函数的返回值示例代码(二)
c
#include <stdio.h>
int main()
{
int a = 0;
int b = 0;
int ret = scanf("%d %d", &a, &b);
//如果读取正常的话,返回的是读取到的数据的个数
printf("ret = %d\n", ret);// 1
printf("a = %d\n", a); //输入值
printf("b = %d\n", b);
return 0;
}
输出结果如下图所示:
10.3 学后小贴士
函数的概念允许程序员将一个复杂的问题分解成更小的子问题,并将其实现和复用。通过函数的调用,可以在程序中多次使用同一段代码,提高代码的可读性和可维护性。同时,函数的使用也简化了程序的控制流程,使得程序的逻辑更加清晰。
十一、数组
11.1 什么是数组?
数组的概念:数组是存储同⼀种数据类型多个元素的集合。也可以看成是⼀个容器。数组既可以存储基本数据类型,也可以存储引⽤数据类型。
11.2如何正确创建数组?
11.2.1 利用while循环打印数组代码示例
c
#include <stdio.h>
int main()
{
int arr[10]={1,2,3,4,5,6,7,8,9,10};
//数组用于存放一组相同类型的元素,是相同类型元素的集合;
//数组的每个元素都有下标,下标从0开始。可以根据数组下标访问数组元素
int i = 0;
while( i < 10 )
{
printf("%d ",arr[i]);
i++;
}
printf("\n");
return 0;
}
输出结果如下图所示:
11.2.2 利用for循环输入并打印数组代码示例
c
#include <stdio.h>
int main()
{
int i = 0;
int j = 0;
int arr[10] = { 0 };
//输入
for (i = 0; i < 10; i++)
{
scanf("%d", &arr[i]);
}
//输出
for (j = 0; j < 10; j++)
{
printf("%d ", arr[j]);
}
printf("\n");
return 0;
}
输出结果如下图所示:
11.3 如何访问数组里的指定元素
c
#include <stdio.h>
int main()
{
int arr[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
//数组下标从0开始,如果一个数组里有m个元素,就可以从arr[0] 开始 访问到 arr[m - 1]
printf("%d\n",arr[4]);
return 0;
}
输出结果如下图所示:
11.4学习小贴士
数组的元素在内存中是连续存放的,是一块连续的空间。而数组的每个元素都有自己唯一的下标,通过下标就可以锁定唯一的元素。如果想要打印或者指定打印某个元素,可以直接通过数组下标访问,数组下标默认从0开始。如果一个数组里有m个元素,就可以从arr[0] 开始一直访问到 arr[m - 1],如果放在的不在这块区域内就会导致越界访问,编译器报错。
十二、操作符
12.1 什么是操作符?
操作符是用来对数值和变量进行某种操作运算的符号。**它可以表示指令系统中的不同操作,每个操作符都有自己特定的语义,具体取决于它所操作的类型。操作符的组合也有特定的顺序,这被称为结合性。操作符的结合性定义了操作符对操作数执行操作的顺序。 操作符可以根据其功能分为多种类别,包括算术操作符、移位操作符、位操作符、赋值操作符、单目操作符、关系操作符、逻辑操作符、条件操作符、逗号表达式、下标引用操作符、函数调用操作符以及结构成员操作符等。每种操作符都有其特定的规则和使用场景 除此之外,操作符还可以根据其在表达式中的位置进一步细分为单目操作符和双目操作符。单目操作符仅接受一个操作数,而双目操作符则需要两个操作数来进行运算。
12.2 C语言中有那些操作符?
C语言中有许多操作符,可以用于对变量进行各种不同的操作。既然上面我们已经简单了解了操作符的概念,接下来我们就要步入正题,正式介绍一下C语言中提供的操作符。
以下是一些常用的C语言操作符:
算术操作符:加、减、乘、除、取余等。例如:+, -, *, /, %
关系操作符:用于比较两个变量的大小关系。例如:==, !=, >, <, >=, <=
逻辑操作符:用于连接两个或多个条件语句。例如:&&, ||, !
位操作符:用于对二进制位进行操作。例如:&, |, ^, <<, >>
赋值操作符:用于给变量赋值。例如:=, +=, -=, *=, /=
条件操作符:也称为三目运算符,用于在条件语句中进行选择。例如:(a>b)?a:b
逗号操作符:用于连接多个表达式,从左到右依次计算并返回最右侧表达式的结果。例如:a=1, b=2, c=a+b
单目操作符: .逻辑非运算符【!】;2.按位取反运算符【~】;3.自增自减运算符【++, --】;4.负号运算符【-】;5.正号运算符【+】;6.类型转换运算符【(类型)】;6.指针运算符和取地址运算符【*和&】;7.长度运算符【sizeof】。
以上就是C语言中常用的操作符了,掌握这些操作符可以帮助我们更好地利用C语言进行编程。
12.2.1 整数除法与小数除法示范用例
c
#include <stdio.h>
int main()
{
int num1 = 0;
int num2 = 0;
printf("请输入两个整数操作数:>");
scanf("%d %d", &num1, &num2);
int c = num1 / num2;
printf("整数除法的结果是:>%d\n", c);
int d = num1 % num2;
printf("整数取模的结果是:>%d\n", d);
//取模操作符两侧的操作数只能是整数,不能是浮点数
float num3 = 0;
float num4 = 0;
printf("请输入两个浮点型操作数:>");
scanf("%f %f", &num3, &num4);
float a = num3 / num4;
printf("小数除法的结果是:>%f\n", a);
//当操作符两侧的操作数都是整数时执行整数除法
//如果要执行浮点数除法,至少有一个操作数为浮点数
return 0;
}
输出结果如下图所示:
12.2.2 赋值操作符示范用例
c
#include <stdio.h>
int main()
{
int a = 10;//初始化
a = 20;//赋值
a += 3;// int a = a + 3;
printf("a = %d\n", a );
a -= 3;// int a = a - 3;
printf("a = %d\n", a );
a *= 3;// int a = a * 3;
printf("a = %d\n", a );
a /= 3;// int a = a / 3;
printf("a = %d\n", a );
return 0;
}
输出结果如下图所示:
12.2.3 单目操作符------前置++/后置++示范用例
c
#include <stdio.h>
int main()
{
int a = 100;
int b1 = a++;//后置++,先将a赋值给b,然后a再自增
printf("a=%d b1=%d\n", a, b1);
//int b=a;a=a+1;
int b2 = ++a;//前置++,先++,后使用
//a=a+1;b=a;
printf("a=%d b2=%d\n", a, b2);
return 0;
}
输出结果如下图所示:
12.2.4 单目操作符------前置--/后置--示范用例
c
#include <stdio.h>
int main()
{
int a = 100;
int b1 = a--;
//b=a,a=a-1;
printf("a=%d b1=%d\n", a, b1);//后置--,先将a赋值给b,然后a再自减
int b2 = --a;//前置--,先--,后使用
//a=a-1;b=a;
printf("a=%d b2=%d\n", a, b2);
return 0;
}
输出结果如下图所示:
12.2.5 单目操作符------逻辑反操作
在C语言中,0表示假,非0表示真。逻辑反操作,也称为逻辑非操作或逻辑取反操作,是通过运算符
!
对一个表达式取其相反的结果。这也就意味着 在编程中,这个操作符可以用于实现布尔值的真假转换,即把真变成假,假变成真。
c
#include <stdio.h>
int main()
{
int flag = 0;
if(flag)//只有表达式内为真才会执行该语句
{
printf("出去喝咖啡。\n");
}
if(!flag)
{
printf("出去喝奶茶。\n");
}
/*
int flag = 7;
if(flag)//只有表达式内为真才会执行该语句
{
printf("出去喝咖啡。\n");
}
if(!flag)
{
printf("出去喝奶茶。\n");
}
*/
return 0;
}
输出结果如下图所示:
12.6 单目操作符------正/负号运算符
c
#include <stdio.h>
int main()
{
int a = -10;
a = +a;
printf("%d\n",a);
a = -a;
printf("%d\n",a);
return 0;
}
输出结果如下图所示:
12.7 单目操作符------sizeof运算符
c
#include <stdio.h>
int main()
{
int a = 10;
printf("%d\n", sizeof(a));
printf("%d\n", sizeof(int));
int arr[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
printf("%d\n", sizeof(arr));
printf("%d\n", sizeof(arr[0]));
int sz = sizeof(arr) / sizeof(arr[0]);
printf("%d\n", sz);
return 0;
}
输出结果如下图所示:
c
#include <stdio.h>
#include <string.h>
int main()
{
char ch[] = "abcdef";
printf("%d\n",strlen(ch));
//strlen是计算字符串的长度的,统计的是\0之前的字符的个数
printf("%d\n",sizeof(ch));
//sizeof计算的是所占内存空间的大小,单位是字节,不在乎内存中存放的是什么。
return 0;
}
输出结果如下图所示:
12.8 单目操作符------强制类型转换操作符
c
#include <stdio.h>
int main()
{
int a = 3.14;
printf("%d\n", a);
return 0;
}
输出结果如下图所示:
c
#include <stdio.h>
int main()
{
int a = (int)3.64;
printf("%d\n", a);
return 0;
}
输出结果如下图所示:
12.9 逻辑操作符------逻辑与&&示范用例
c
#include <stdio.h>
int main()
{
int age = 0;
scanf("%d", &age);
if (age >= 18 && age <= 30)
{
printf("青壮年。\n");
}
return 0;
}
c
#include <stdio.h>
int main()
{
int num1 = 0;
int num2 = 10;
int ret1 = num1 && num2;
printf("%d\n", ret1);
int num3 = 10;
int num4 = 0;
int ret2 = num3 && num4;
printf("%d\n", ret2);
int num5 = 20;
int num6 = 10;
int ret3 = num5 && num6;
printf("%d\n", ret3);
return 0;
}
输出结果如下图所示:
12.10 逻辑操作符------逻辑或||示范用例
c
#include <stdio.h>
int main()
{
int num1 = 0;
int num2 = 10;
int ret1 = num1 || num2;
printf("%d\n", ret1);
int num3 = 10;
int num4 = 0;
int ret2 = num3 || num4;
printf("%d\n", ret2);
int num5 = 0;
int num6 = 0;
int ret3 = num5 || num6;
printf("%d\n", ret3);
return 0;
}
输出结果如下图所示:
12.11 条件操作符示范用例
学习小贴士: 条件操作符的表达式书写形式为:表达式1?表达式2:表达式3 ; 先求解表达式1,若其值为真(非0)则将表达式2的值作为整个表达式的取值,否则(表达式1的值为0)将表达式3的值作为整个表达式的取值。
c
#include <stdio.h>
int main()
{
int a = 0;
int b = 0;
int max = 0;
scanf("%d %d", &a , &b);
/*
if(a > b)
{
m = a;
}
else
{
m = b;
}
*/
max = a > b ? a : b;
printf("%d\n",max);
return 0;
}
输出结果如下图所示:
12.12 逗号表达式操作符示范用例
学习小贴士: 逗号表达式是C语言中的一种特殊语法,用于连接多个表达式并按照特定的顺序进行计算。**它的优先级是最低的,这就意味着它会首先计算左边的表达式,然后再计算右边的表达式。 逗号表达式的一般形式是将两个或更多的表达式用逗号分隔开来,如 (expression1, expression2, expression3)。在这个例子中,expression1 将被计算并作为第一个参数传递给下一个表达式(即expression2),然后 expression2的结果会作为第二个参数传递给第三个表达式(即 expression3)。最终的表达式的结果是由最后一个表达式的结果决定的。
c
#include <stdio.h>
int main()
{
int a = 3;
int b = 5;
int c = 0;
int d = (a += 3, b -= a, c = a + b , c - 2);
printf("%d\n", d);
return 0;
}
输出结果如下图所示:
12.13 下标引用操作符【】示范用例
学习小贴士: C语言中的下标引用操作符[ ]主要用于访问数组或指针所指向的元素。具体来说,如果你有一个数组
arr
和一个整数index(索引),你可以通过以下方式使用下标运算符: arr[index]:这将返回数组的第index个元素的值。如果index超出了数组的有效范围或者数组的长度,那么程序会抛出数组越界异常。
c
#include <stdio.h>
int main()
{
int arr[10] = { 1, 2, 3, 4, 5, 6};//不完全初始化,剩余的元素全部默认初始化为0
printf("%d\n", arr[8]);
return 0;
}
输出结果如下图所示:
12.14 函数调用操作符( )示范用例
学习小贴士: 函数调用操作符是一种用于调用函数的符号。在大多数编程语言中,函数调用操作符通常是一对圆括号(),其中包含函数的参数列表。当程序运行到函数调用操作符时,它会将控制权转移到该函数,并将参数传递给函数。函数执行完毕后,程序将返回到调用点,并继续执行下一条指令。 函数调用操作符不仅可以调用内置函数,还可以调用自定义函数。在调用自定义函数时,需要在函数声明中定义参数列表和函数体。当函数被调用时,其参数将被传递给函数,并在函数体中进行处理。 函数调用操作符是程序中非常重要的一部分,因为它允许程序员调用和重用函数,从而简化了代码并提高了程序的可读性和可维护性。
c
#include <stdio.h>
#include <string.h>
int main()
{
int len = strlen("abcde");//函数调用操作符
printf("%d\n" , len);
return 0;
}
输出结果如下图所示:
十三、常见关键字
13.1 C语言中的常见关键字有哪些?
auto :声明自动变量 break:跳出当前循环 case:开关语句分支 char :声明字符型变量或函数返回值类型 const :声明只读变量 continue:结束当前循环,开始下一轮循环 default:开关语句中的"默认"分支 do :循环语句的循环体 double :声明双精度浮点型变量或函数返回值类型 else :条件语句否定分支(与 if 连用) enum :声明枚举类型 extern:声明变量或函数是在其它文件或本文件的其他位置定义 float:声明浮点型变量或函数返回值类型 for:一种循环语句 goto:无条件跳转语句 if:条件语句 int: 声明整型变量或函数 long :声明长整型变量或函数返回值类型 register:声明寄存器变量 return :子程序返回语句(可以带参数,也可不带参数) short :声明短整型变量或函数 signed:声明有符号类型变量或函数 sizeof:计算数据类型或变量长度(即所占字节数) static :声明静态变量 struct:声明结构体类型 switch :用于开关语句 typedef:用以给数据类型取别名 unsigned:声明无符号类型变量或函数 union:声明共用体类型 void :声明函数无返回值或无参数,声明无类型指针 volatile:说明变量在程序执行中可被隐含地改变 while :循环语句的循环条件
13.2 auto 关键字代码示例
c
#include <stdio.h>
int main()
{
auto int age = 10;//局部变量自动创建,自动销毁的自动变量
}
13.2 typedef 关键字代码示例
学习小贴士: typedef为C语言的关键字,作用是为一种数据类型定义一个新名字。这里的数据类型包括内部数据类型(int,char等)和自定义的数据类型(struct等)。 在编程中使用typedef目的一般有两个,一个是给变量一个易记且意义明确的新名字,另一个是简化一些比较复杂的类型声明。
c
#include <stdio.h>
typedef unsigned int uint;//类型重定义
int main()
{
unsigned int age = 10;
uint age2 = 20;
printf("%d %d\n", age, age2);
return 0;
}
输出结果如下图所示:
13.3 static 修饰局部变量代码示例
学习小贴士: static可使得局部变量出了⾃⼰的范围也不会销毁,本质上是改变了局部变量的⽣命周期,但其作⽤域还是局部的。 详细点说,就是有时我们希望函数中局部变量的值在函数调⽤结束后不销毁⽽继续保留原值,即希望其占⽤的存储单元不释放。在下⼀次再调⽤该函数时,该变量已有值(就是上⼀次函数调⽤结束时的值)。 这时就该指定该局部变量为"静态局部变量",⽤关键字static 对其进⾏声明。
c
#include <stdio.h>
void test()
{
static int n = 0;
//局部变量n从栈区改至存放至静态区,作用域不变,生命周期延长。输出1~10
n++;
//如果是全局变量被static修饰后,该全局变量只能在本源文件内使用,不能在其他源文件内使用
printf("%d ", n);
//一个函数被static修饰后,该函数只能在本源文件内使用,不能在其他源文件内使用。
}
int main()
{
int n = 0;
for(n = 0 ; n < 10;n++)
{
test();
}
return 0;
}
输出结果如下图所示:
13.4 static 修饰全局变量代码示例
学习小贴士: 当⼀个进程的全局变量被声明为static之后,它的中⽂名叫静态全局变量。静态全局变量和其他的全局变量的存储地点并没有区别,都是在.data段(已初始化)或者.bss段(未初始化)内,但是它只在定义它的源⽂件内有效,其他源⽂件⽆法访问它。 根据这个原理,我们可以在多个⽂件中定义相同名字的全局变量⽽不影响,可以重名。
13.4.1 未被static修饰的全局变量
输出结果如下图所示:
13.4.2 被static修饰的全局变量
输出结果如下图所示:
13.5 static 修饰函数代码示例
13.5.1 未被static修饰的函数
输出结果如下图所示:
13.5.1 被static修饰的函数
输出结果如下图所示:
十四、指针
14.1 什么是指针?
指针,是C语言中的一个重要概念及其特点,也是掌握C语言比较困难的部分。指针也就是内存地址,指针变量是用来存放内存地址的变量,在同一CPU构架下,不同类型的指针变量所占用的存储单元长度是相同的------在32位平台机器下(x86)大小为4字节,64位平台机器下(x64)机器下大小为8个字节。而存放数据的变量因数据的类型不同,所占用的存储空间长度也不同。有了指针以后,不仅可以对数据本身,也可以对存储数据的变量地址进行操作。 指针描述了数据在内存中的位置,标示了一个占据存储空间的实体,在这一段空间起始位置的相对距离值。在 C/C++语言中,指针一般被认为是指针变量,指针变量的内容存储的是其指向的对象的首地址,指向的对象可以是变量(指针变量也是变量),数组,函数等占据存储空间的实体。
14.2 计算指针大小代码示例
c
#include <stdio.h>
int main()
{
printf("%zd\n", sizeof(char*));
printf("%zd\n", sizeof(short*));
printf("%zd\n", sizeof(int*));
printf("%zd\n", sizeof(double*));
//在32位平台机器下(x86)大小为4字节,64位平台机器下(x64)机器下大小为8个字节。
return 0;
}
输出结果如下图所示:
14.3 指针变量在内存中的存储代码示例
c
#include <stdio.h>
int main()
{
int num = 19;
printf("%p\n",&num);
//打印出的是该变量里最小的那个地址
return 0;
}
输出结果如下图所示:
14.3 通过指针修改变量代码示例
c
#include <stdio.h>
int main()
{
int num = 10;
int* pa = #
//将变量num的地址存放至整型指针变量pa中存放,后续可以通过解引用的方式直接修改num的值
*pa = 20;
printf("%d\n", num);
char ch = "w" ;
char* pb = &ch;
*pb = "q";
printf("%c\n",ch);
return 0;
}
输出结果如下图所示:
十五、结构体
15.1 什么是结构体?
结构体是C语言中一种重要的数据类型,该数据类型由一组称为成员(或称为域,或称为元素)的不同数据组成,其中每个成员可以具有不同的类型。结构体通常用来表示类型不同但是又相关的若干数据。 结构体类型不是由系统定义好的,而是需要程序设计者自己定义的。C语言提供了关键字struct来标识所定义的结构体类型。 关键字struct和结构体名组合成一种类型标识符,其地位如同通常的int、char等类型标识符,其用途就像 int 类型标识符标识整型变量一样可以用来定义结构体变量。定义变量以后,该变量就可以像定义的其他变量一样使用了;成员又称为成员变量,它是结构体所包含的若干个基本的结构类型,必须用"{}"括起来,并且要以分号结束,每个成员应表明具体的数据类型。
15.2 结构体成员变量是如何访问的?
15.2.1 结构体变量.成员名 访问变量 代码示例
c
#include<stdio.h>
//定义一个学生类型
struct stu
{
char name[20];
char sex[3];
int age;
};
int main()
{
struct stu s = {"zhangsan","男",20 };
struct stu s2 = { "如花","女",19 };
//结构体变量.成员名
printf("%s\n",s2.name);
printf("%s\n", s2.sex);
printf("%d\n", s2.age);
return 0;
}
输出结果如下图所示:
15.2.2 结构体的指针变量->成员名 访问变量 代码示例
c
#include<stdio.h>
//定义一个学生类型
struct stu
{
char name[20];
char sex[3];
int age;
};
void Print(struct stu* ps)
{
//结构体的指针变量->成员名
printf("%s %s %d\n", (*ps).name, (*ps).sex, (*ps).age);
printf("%s %s %d\n", ps->name, ps->sex, ps->age);
}
int main()
{
struct stu s = {"zhangsan","男",20 };
struct stu s2 = { "如花","女",19 };
Print(&s);
return 0;
}
输出结果如下图所示: