C 介绍
1982年,Bjarne Stroustrup博士在C语言的基础上引入并扩充了面向对象的概念,发明了一 种新的程序语言。为了表达该语言与C语言的渊源关系,命名为C 。因此:C 是基于C语言而 产生的,它既可以进行C语言的过程化程序设计,又可以进行以抽象数据类型为特点的基于对象的 程序设计,还可以进行面向对象的程序设计。 C 在C语言的基础上添加了不少新的东西。 让我们看看C 这门语言值不值得学习:
可以从上图看见C 一直都保持在前五,是一门不可或缺的编程语言,让我们来看看C 的应用领域
C 的应用领域
- 操作系统以及大型系统软件开发 所有操作系统几乎都是C/C 写的,许多大型软件背后几乎都是C 写的,比如: Photoshop、Office、JVM(Java虚拟机)等,究其原因还是性能高,可以直接操控硬件。
- 服务器端开发 后台开发:主要侧重于业务逻辑的处理,即对于前端请求后端给出对应的响应,现在主流采 用java,但内卷化比较严重,大厂可能会有C 后台开发,主要做一些基础组件,中间件、 缓存、分布式存储等。服务器端开发比后台开发跟广泛,包含后台开发,一般对实时性要求 比较高的,比如游戏服务器、流媒体服务器、网络通讯等都采用C 开发的。
- 游戏开发 PC平台几乎所有的游戏都是C 写的,比如:魔兽世界、传奇、CS、跑跑卡丁车等,市面上 相当多的游戏引擎都是基于C 开发的,比如:Cocos2d、虚幻4、DirectX等。三维游戏领 域计算量非常庞大,底层的数学全都是矩阵变换,想要画面精美、内容丰富、游戏实时性 搞,这些高难度需求无疑只能选C 语言。比较知名厂商:腾讯、网易、完美世界、巨人网 络等。
- 嵌入式和物联网领域 嵌入式:就是把具有计算能力的主控板嵌入到机器装置或者电子装置的内部,能够控制这些 装置。比如:智能手环、摄像头、扫地机器人、智能音响等。 谈到嵌入式开发,大家最能想到的就是单片机开发(即在8位、16位或者32位单片机产品或者 裸机上进行的开发),嵌入式开发除了单片机开发以外,还包含在soc片上、系统层面、驱动 层面以及应用、中间件层面的开发。 常见的岗位有:嵌入式开发工程师、驱动开发工程师、系统开发工程师、Linux开发工程 师、固件开发工程师等。 知名的一些厂商,比如:以华为、vivo、oppo、小米为代表的手机厂;以紫光展锐、乐鑫为 代表的芯片厂;以大疆、海康威视、大华、CVTE等具有自己终端业务厂商;以及海尔、海 信、格力等传统家电行业。 随着5G的普及,物联网(即万物互联,)也成为了一种新兴势力,比如:阿里lot、腾讯lot、京 东、百度、美团等都有硬件相关的事业部。
- 数字图像处理 数字图像处理中涉及到大量数学矩阵方面的运算,对CPU算力要求比较高,主要的图像处理 算法库和开源库等都是C/C 写的,比如:OpenCV、OpenGL等,大名鼎鼎的Photoshop 就是C 写的。
- 人工智能 一提到人工智能,大家首先想到的就是python,认为学习人工智能就要学习python,这个 是误区,python中库比较丰富,使用python可以快速搭建神经网络、填入参数导入数据就 可以开始训练模型了。但人工智能背后深度学习算法等核心还是用C 写的。
- 分布式应用 近年来移动互联网的兴起,各应用数据量业务量不断攀升;后端架构要不断提高性能和并发 能力才能应对大信息时代的来临。在分布式领域,好些分布式框架、文件系统、中间组件等 都是C 开发的。对分布式计算影响极大的Hadoop生态的几个重量级组件:HDFS、 zookeeper、HBase等,也都是基于Google用C 实现的GFS、Chubby、BigTable。包括分 布式计算框架MapReduce也是Google先用C 实现了一套,之后才有开源的java版本。
C 的关键字
C 的关键字相对于C语言来说增加了将近一倍,我们重点介绍个别
1.namespace
为什么C 会引入namespace
这个关键词呢
我们先来举个例子,下面代码在C语言的环境下会报错。
#include<stdio.h>
#include<stdlib.h>
int rand = 0;
//命名冲突
//我们和库,会产生冲突
//所以在C 中只能改名字,不能改库
int main()
{
printf("%d ", rand);
printf("hello world");
}
注意:上面代码会引起歧义,C语言的编译器不知道rand具体是函数还是变量,因为rand
也是stdlib.h
中的一个库函数,所以C语言不知道将其识别为自定义的变量还是将其识别为库函数。
在这种情况下,大佬比雅尼就提出了命名空间的概念,为的就是防止一些命名冲突。
namespace的使用规则
namespace和结构体相差不大,但是在namespace中可以放结构体,函数,变量等等… 下面给出例子;
代码语言:javascript复制namespace lyrics
{
struct Node
{
struct Node* next;
int val;
};
int b = 0;
int Add(int a, int b)
{
return a b;
}
}
上面就是我们定义的一个namespace。 如何使用namespace呢? 首先我们要了解一下,编译器是如何寻找我们定义的变量的,首先,编译器在当前作用域中找,如果当前作用域没有,就在全局作用域中找,如果全局作用域中没有,最后,如果我们在前面声明了namespace的话,最后再在namespace中找。
第一种方式:指定展开
这里讲到了指定展开就必须提一下域作用限定符(::
)用域作用限定符就可以对某个域中的一个变量或者函数或者是结构体进行指定展开,例子如下:
int main()
{
int i = lyrics::Add(1, 8);
lyrics::b;
struct lyrics::Node nenwode;
}
第二种方式:全展开 全展开和头文件的展开是不一样的,命名空间的全展开是指展开这个域,影响的是编译器的查找规则,而头文件的展开是库里面包含的一些库里的东西展开放进去。 接下来展示一下:
代码语言:javascript复制using namespace lyrics;
int main()
{
int i = Add(1, 8);
b;
struct Node nenwode;
}
第三种方式:指定某一个展开 指定某一展开和全展开不一样,指定某一个展开就相当于,把某一个常用的结构体或者变量或者函数进行展开,而不是将所有的内部的东西展开。 下面举一个例子:
代码语言:javascript复制using lyrics::Add;
using lyrics::b;
using lyrics::Node;
int main()
{
int i = Add(1, 8);
b;
struct Node nenwode;
}
命名空间还可以根据前面定义的变量,自动去寻找我们的函数,就比如一个参数是用一个bit作用中的结构体定义的,如果我下面不指定函数用这个结构体变量,编译器会自动去这个bit的命名空间中寻找。
C 的输入&输出
C 中的输入输出的头文件是iostream
这里就要用到了C 中的流插入<<
,接下来举个例子:
#include<iostream>
//std是库的命名空间,是将库函数放在这个命名空间中
using std::cout;
using std::endl;
int main()
{
//<<流插入
int i = 0;
double j = 1.11;
//特点是自动识别类型
cout << "hello world" << " " << i << " " << j << endl << endl;
cout << "hello world" << " " << i << " " << j << endl << endl;
std::cout << "hello world" << " " << i << " " << j << std::endl << endl;
return 0;
}
注意:C 中使用cout和cin必须用标准命名空间std
C 中的输入:cin
,cin用的是>>这个符号。
int main()
{
//<<流插入
int i = 0;
std::cin >> i;
double j = 1.11;
//特点是自动识别类型
}
总结
C 在C语言的基础上进行了扩充,弥补了很多C语言的局限,这样也使得C 变的相对复杂。