前言
想必,有些童鞋刚接触到C语言,就像小编我一样根本不知道C语言究竟在讲的是什么?那么恭喜你,你发现了一个宝藏。那么,废话不多说,就请跟随小编的脚步进行了解初识C语言吧!
正如题目所说,初始C语言是对C语言有一个大概的认识,搭建起C语言的框架。那么,小编要开始讲解了。 记得这一章主要是初始C语言的一个大纲,内容中含有大量的链接是为了详细地讲解每一部分的内容。
一、什么是C语言
首先,请你先用自己的话解释C语言是什么?(这个要画重点,有可能面试官会问)
**********************************************************************************************
语言:汉语,日语,英语等。语言是一个自然语言,是人与人交流的语言。
计算机语言:类比过来,是人与计算机之间的交流。
***********************************************************************************************
C语言是一门通用计算机编程语言(这就是C语言牛逼的地方),广泛用于底层开发。
如果读者想要了解更多有关C语言的功能与作用,在度娘中,你可以点击这个链接: C语言的作用与功能 。
对于底层开发,下面进行解释一下:一般地,电脑分为上层软件和下层软件,而下层软件是底层,C语言就广泛应用于底层开发。
计算机处理的是“二进制的信息”(这个点很重要,因为以后如果讲与内存有关的内容要带入这个点)。在进行C语言的学习中,我们需要使用集成开发环境。集成开发环境是集成了很多的子程序:编辑、编译、链接、运行、调试。(小编我也正在了解这些内容,就不好帮你们讲解这部分内容,如果感兴趣的话,小编就在这里为大家介绍一本书:《程序员的自我修养——链接、装载与库》。这本书详细解说了这五个步骤是起到什么作用。等小编读完后,定会做一篇博客进行讲解与分析。)
二、第一个C语言程序
*******************************************************************************************************
我们在了解完C语言是什么后,我们需要了解如何使用集成开发环境去完成第一个C语言程序。下面,大部分人在初学C语言时,都不会使用的集成开发环境。小编我也会带着大家如何使用VS2019,因为其他编译器都太古老了。看下面的图进行你的第一步吧!
********************************************************************************************************
*******************************************************************************************************
在进行计算机语言的学习中,有一个梗就是"hello world",因为基本大家的第一个C语言程序都是从"hello world"开始的,那么对于一个这么简单的程序,我们可以从中学习到什么呢?
*******************************************************************************************************
#include <stdio.h> int main() { printf("hello world\n"); return 0; }
首先,可以知道C语言中所有字符都是英文的字符。其次,在c语言代码中都是从main函数的第一行开始的,main函数是程序的入口,一个工程中main函数有且只有一个。其中代码中的printf函数是编译器自带的函数,可以直接使用。最后,是头文件,而.c文件是源文件。在使用函数时,要引用对应的头文件。
最后再讲一下main函数:main函数有三种写法,第一种就是 int main()(这个是最简单的,也是我们最常用的);第二种是 int main(void),这种写法中明确表示main函数不接收参数;第三种是 int main (int argc , char* arr[]),在这样写的时候,有两个参数被送给了main(),一个参数是描述了命令行参数的个数,一个是命令行中的数组,通常称为argv,命令行参数都是字符串。详情请看这条链接:【命令行参数_百度百科】
三、数据类型
*******************************************************************************************************
C语言的数据类型有:char(字符数据类型) short(短整型)
int(整型) long(长整型)
long long(更长的整型) float(单精度浮点数) double(双精度浮点数)。
*******************************************************************************************************
在了解数据类型前,我们先探究为什么要写程序?是为了用程序解决生活中的一些问题。在现实生活中,我们的各种数据有很多不同的类型,为了更加丰富的表达生活中的各种值,所以在C语言程序中设置这么多数据类型。
每种类型的大小是多少?
******************************************************************************************************* 在这里提一句计算机中常见的单位:bit(比特),byte(字节),KB,MB,GB,TB,PB。他们的单位换算为:1 byte = 8 bit
1 KB = 1024 byte
1 MB = 1024 KB
1 GB = 1024 MB
1 TB = 1024 GB
1 PB = 1024 TB。
*******************************************************************************************************
四、变量,常量
在生活中有些值是不变的(比如:圆周率,性别,身份证号码,血型等等),有些值是可变的(比如:年龄,体重,薪资等等),引入了变量和常量的概念。
首先,先讲述一下变量:
4.1 定义变量的方法
语法形式为:type + name。代码如下:
int age = 150; float weight = 45.5f; //浮点数默认为双精度浮点数,在后面加个f,说明是单精度浮点数类型 char ch = 'w';
4.1.1 变量的命名
*******************************************************************************************************
基本规则如下:
1)只能由字母(包括大写和小写),数字,下划线组成;
2)不能以数字开头;
3)长度不能超过63个字符(这纯纯抬杠,纯路人,没必要);
4)区分大写,小写;
5)变量名不能使用关键字;
6)变量的名字尽量有意义(提醒我们要了解部分英语单词)。
*******************************************************************************************************
4.2 变量的分类
变量分为局部变量和全局变量,当全局变量和局部变量同名时,局部变量优先。
4.3 变量的使用
#include <stdio.h> int main() { int num1 = 0; int num2 = 0; int sum = 0; printf("请输入两个操作数:>"); scanf("%d %d", &num1, &num2); sum = num1 + num2; printf("sum = %d\n", sum); return 0; }
在vs编译时会发现,我们在这里会出现4996警告。
为什么会出现这个警告呢?是因为在vs中输入函数,人家自己有定义是scanf_s,而用scanf函数不安全。
那如何消除这个警告呢?(一共有三种方法)
首先第一种方法很简单,就是直接把scanf改成scanf_s,因为scanf_s函数是vs提供的,这样vs就不会报错了,这种方式简单快捷,但是也有不足之处,这样写出的代码没有可移植性,及直接复制粘贴后在别的编译软件上无法直接使用。那么就需要我们的第二种方法了。
第二种方法中,用#pragma warning(disable:4996)代码会让编号为4996的警告错误失效,vs就不会管你的这个代码是否正确。但是,这种方法每次创建工程后都需要进行编写,比较麻烦。
最后,第三种方法是一劳永逸的,首先,你需要在你的vs文件夹中找到这么一个叫newc++file.cpp的文件,在文件中写入#define _CRT_SECURE_NO_WARNINGS,保存关闭即可,以后每当你打开vs,新建项目的时候,第一行就会自动出现这行代码,有效解决了咱们的困扰,一劳永逸。
4.4 变量的作用域和生命周期
4.4.1 作用域
作用域是一个范围,其是一个程序设计概念,通常来说,一段代码中所用到的名字并不总是有效的,而限定这个名字的可用性的代码范围就是这个名字的作用域。
下面是小编对于作用域做的总结:
1)局部变量的作用域是变量所在的局部范围。
2)全局变量的作用域是整个工程。
4.4.2 生命周期
生命周期是一个时间周期,变量的生命周期是变量的创建到变量的销毁之间的时间段。
1)局部变量的生命周期是:进入作用域生命周期开始,出作用域生命周期结束。
2)全局变量的生命周期是:整个程序的生命周期。
下面是小编对于生命周期做的总结:
如何理解程序?(这个萌新不必在意,在后面小编我会将这个内容单独拿出来讲解)
在创建一个工程中,我们可以创建多个源文件,比如用声明外部符号:"extern",可以将一个源文件定义的全局变量在另一个源文件中使用。如下图:
然后讲一下常量:
4.5 常量
C语言中常量分为一下几种:字面常量,const修饰的常变量,#define 定义的标识符常量,枚举常量
下面小编来带着大家一一分析吧:
4.5.1 字面常量
字面常量没有什么可以说的地方,直接写出的值;
4.5.2 const 修饰的常变量
const 修饰的常变量在C语言中只是在语法层面限制了变量不能直接被改变,但是他本质上还是一个变量,所以叫常变量。
为什么const 修饰在C语言中是常变量呢?
因为在C语言中,如果在数组中的方括号引用const 修饰的常变量,代码在编译时会出现警告,而在C++中,把const 修饰的变量看成常量。
4.5.3 #define 定义的标识符常量
#define定义的标识符可以在数组中使用。
4.5.4 枚举常量
枚举常量默认从0开始,依次向下递增1。
五、字符串+转移字符+注释
5.1 字符串
在C语言中没有字符串类型,字符串类型是可以存放在字符数组中的。
“hello world”这种由双引号引起来的一串字符称为字符串面值,或简称字符串。字符串的结束标志是一个'\0'的转义字符,在计算字符串长度的时候 \0 是结束标志,不算字符串内容。
char arr[] = "hello world"; char arr[] = {'h','e','l','l','t'}; //最后输出该数组时会出现乱码的情况 char arr[] = {'h','e','l','l','t','\0'};
定义字符串的数组中,在数组结尾需要加入 \0 来提示编译器是字符串结束标志。
5.2 转义字符
转义字符顾名思义就是转变原来的意思,是为了防止一些符号写在一起时,编译器误解他们的意思。下面,我们来进行介绍几个常用的转义字符。
字符在计算机存储都有编码,ASCLL码值的取值范围是:0 - 127,后期拓展到了 0 - 255。
下面是一道经典的题目:(这个题目的答案是14)
#include <stdio.h> int main() { printf("%d\n", "c:\test\628\test.c"); return 0; }
在这道题中,我们要小心这几个坑:1)转义字符,因为他们都在转义字符中都没有写入 '\' ,所以要将他们当做字符来看待。2)就是这个八进制的转义字符,因为会给你塞个8,但八进制中不会出现8这个数字。
5.3 注释
这一部分还是比较简单的,在程序员中的世界中,有时候代码会进行一些冗余,代码中有些地方理解起来会比较费解,需要在旁边进行注释;有时候不需要的代码需要进行删除操作,如果不想删除,也可以进行注释。
注释有两种类型:一种是C语言风格的注释(一般都不用这个):/* */,另一种是c++风格的注释://。
六、选择语句
if else语句在C语言中属于选择结构。
七、循环语句
循环语句中有三种形式:while(),for(), do while()。
他们有一些区别使得他们适用的场景不太相同,如果已知循环的次数用for循环,如果不知道循环的次数用while循环,如果想要先循环一次则用do while循环。
八、函数
在数学中,函数是描述变量之间的关系,在C语言中,我们用函数其实也是定义一个关系。
#include <stdio.h> //函数的定义和声明 int ADD(int x, int y) { return x + y; } int main() { int a = 0, b = 0; int sum = 0; scanf("%d %d", &a, &b); //函数的调用 sum = ADD(a, b); printf("%d\n", sum); return 0; }
函数的特点是简化代码,代码复用。
九、数组
C语言中,数组是用来存储一组相同类型元素的集合。
9.1 数组定义
数组可以初始化和不完全初始化。
完全初始化:int arr[4] = {2,3,4,5};
不完全初始化:int arr[4] = {0};
9.2 数组的下标
C语言规定:数组的每一个元素都有一个下标,下标是从0开始的,数组也可以通过下标来访问。
9.3 数组的使用
#include <stdio.h> int main() { int arr[10] = {0}; //利用循环 输入 输出 for(int i = 0; i < 10; i++) { scanf("%d", &arr[i]); } for(int i = 0; i < 10; i++) { printf("%d ", arr[i]); } printf("\n"); return 0; }
十、操作符
10.1 算术操作符
+ - * / %
10.2 移位操作符
>> <<
10.3 位操作符
& ^ |
10.4 赋值操作符
= += -= *= /= ^= |= >>= <<=
10.5 单目操作符
! 逻辑反操作符 在C语言中,0表示假,非0表示真
sizeof 操作数的类型长度(以字节为单位) 这个最不像操作符,要记住
-- 前置--,后置-- 前置是先加1,后使用;后置是先使用,后加1
++ 前置++,后置++ 前置,后置看符号位置,自己加1,无所谓
10.6 关系操作符
> >= < <= != ==
10.7 逻辑操作符
&& 逻辑与 全真为真
|| 逻辑或 全假为假
在这里想起了朋友的一道题:
我刚看到这个题是有疑惑的,因为b和c选项感觉都是错的,其实并不是。因为c选项是涉及一些知识点是我不知道的,因为有逻辑短路,在C语言中,我们进行运算的时候,我们需要进行优化代码,不让这个程序进行超负荷的运算。在程序中,因为,a||(b = c)是这个逻辑运算,为什么会有逻辑短路呢?为了减少程序的计算量,在进行这个逻辑运算的时候,C语言采用了在保持原逻辑运算正确的同时,通过已确定表达式的确切值的情况下,不计算后面的运算来简化运算。
在或运算中,如果a为真,后面的值不管是什么,我们都不需要进行计算,因为程序的结果已经知道了,就应该进行逻辑短路,然后就不计算b = c,所以没有将c赋值给b, b还是等于原值。如果a为假,说明后面的结果可能会影响整个结果,所以就不能进行逻辑短路。
10.8 条件操作符
exp1 ? exp2 : exp3 三目操作符,如果1成立,那么输出2,否则输出3
10.9 逗号表达式
exp1,exp2,exp3,exp4 从左向右依次计算,整个表达式的结果是最后一个表达式的值。
10. 10 下标引用、函数调用和结构成员
[ ] () . ->
十一、常见关键字
这些常见关键字分为:类型,循环,分支,声明,函数等等;
类型:auto(自动),char,double,enum,float,int,long,short,signed,unsigned,union,void,sizeof,struct,typedef。
循环:break,continue,do while(),for,continue。
分支:switch,break,case,default,if else,goto。
声明:extern(声明外部变量),register,static,volatile。
函数:return。
11.1 关键字 register
其是一个寄存器关键字,用register声明的变量是寄存器变量,是存放在CPU的寄存器里的。寄存器变量和普通变量比起来速度上的差异很大,毕竟CPU的速度远远大于内存的速度。寄存器有这么两个特点,一个是运算速度快,一个是不能取地址。但是在寄存器中的变量是不能取地址的,编译器会报错。
11.2 关键字 typedef
typedef 顾名思义是类型定义,这里应该理解为类型重命名。目的是简化代码。
11.3 关键字 static
在C语言中,static是用来修饰变量和函数的。
有三个用法:
1)修饰局部变量,称为静态局部变量;
2)修饰全局变量,称为静态全局变量;
3)修饰函数,称为静态函数。
11.3.1 修饰局部变量
在c/c++程序中,在语言中,内存被分为三个部分:栈区,堆区,静态区。
一个普通的局部变量进入函数创建,出函数销毁,但被static修饰后,进入函数已经创建好了(因为在反汇编中,static 修饰的变量没有汇编语言。)出函数不销毁,多次调用函数=时,共享一个变量。
本质:普通局部变量放在栈区,被static修饰放在静态区中。
11.3.2 修饰全局变量
在C语言中,每一个.c文件单独经过编译器处理的,全局变量具有外部链接属性,这种属性决定了全局变量在多个文件之间可以使用。但被static修饰后,将全局变量的外部链接属性变成内部链接属性,使得这个全局变量只能在本文件内使用,不能在其他源文件内使用。
11.3.3 修饰函数
函数的属性和全局变量有点相似,函数也是具有外部链接属性(可以跨文件使用),一旦被static修饰,使得这个函数只能在本文件中使用,不能在其他源文件中使用。
十二、#define 定义常量和宏
12.1 #define定义标识符常量
12.2 #define定义宏
十三、指针
13.1 内存
内存是电脑中特别重要的存储器,计算机中程序的运行都是在内存中运行的。所以为了有效的使用内存,就把内存划分为一个个小小的内存单元,每一个内存单元的大小为1个字节(因为最小的数据类型为char类型,char类型的字节是1个字节),为了能够有效的访问到内存的每个单元,就给内存单元编号的,这些编号被称为该内存单元的地址。
内存和硬盘要分清楚。
32位机器中,有32个地址线,每一个地址线是0/1,也就有2的32次方个地址,能够管理4GB的内存。二进制,八进制,十进制,十六进制都是数值的表达形式。
总结:1.内存会被划分为以字节为单位的一个个内存单元;
2.每个内存单元都有编号,编号 = 地址 = 指针;
3.C语言中创建的变量,其实是向内存中申请一块空间;
4.&a时,拿出4个字节中较小的那个字节地址;
5.指针变量存储的是地址;
6.可以通过指针变量找到a。
13.2 指针变量的大小
指针变量的大小取决于地址的大小,32位机器平台下的地址是32个bit位(即4个字节),64位机器平台下的地址是64个bit位(即8个字节)。
十四、结构体
C语言中有数组的概念,但是数组太局限,只能存储一个相同类型的数据。但现实生活中,这个数据比较复杂,仅仅用数组无法将其表达成功,所以C语言引入这个结构体来存放不同类型的数据。
如果要求结构体中某一元素,需要用该元素相对应的指针类型进行取地址。