🥦 bitset 类型
type
status
date
slug
summary
tags
category
icon
password
Property
 
标准库定义了bitset 类,使得位运算的使用更为容易, 并且能够处理超过最长整型类型大小的位集合。bitset类定义在头文件bitset
 
给40亿个不重复的无符号整数,没排过序。给一个无符号整数,如何快速判断一个数是否在这40亿个数中?
要判断一个数是否在某一堆数中,可能会想到如下方法:
  • 将这一堆数进行排序,然后通过二分查找的方法判断该数是否在这一堆数中
  • 将这一堆数插入到unordered_set容器中,然后调用find函数判断该数是否在这一堆数中
但问题是这里有40亿个数,若是要将这些数全部加载到内存当中,那么将会占用16G的空间,空间消耗是很大的。因此从空间消耗来看,上面这两种方法实际都是不可行的。
实际在这个问题当中,只需要判断一个数在或是不在,即只有两种状态,那么可以用一个比特位来表示数据是否存在,如果比特位为1则表示存在,比特位为0则表示不存在。
notion image
无符号整数总共有 个,因此记录这些数字就需要个比特位,也就是512M的内存空间,内存消耗大大减少。
 
🥦 正则表达式
type
status
date
slug
summary
tags
category
icon
password
Property
 
正则表达式是一种描述字符序列的方法。C++11中有正则表达式库(RE库),定义在头文件regex
regex库组件:
notion image
 
regex类表示一个正则表达式,它支持的一些操作:
notion image
在定义或赋值一个regex时,可以指定一些标志位影响regex如何匹配,上图中最后六个即为编写正则表达式时所用的语言,默认为ECMAScript,即ECMA-262语法标准,这也是很多Web浏览器所使用的。
 
函数regex_matchregex_search确定一个给定字符序列与一个给定regex是否匹配:
  • 整个输入序列与表达式匹配,regex_match返回true
  • 输入序列中一个子串与表达式匹配,regex_search返回true
🥦 随机数
type
status
date
slug
summary
tags
category
icon
password
Property
 
C++11前,依赖C库的rand函数生成随机数,它生成均匀分布的伪随机整数,范围为0~一个系统相关的最大值(至少为32767)之间,它不能生成任意范围的随机数,不能生成随机浮点数,也不能生成非均匀分布的随机数,为解决这些不足所作的一些操作可能会引入非随机性。
 
C++11引入了头文件random,其中包含随机数引擎类和随机数分布类:
notion image
 
标准库定义了多个随机数引擎,区别在于性能和随机性质量不同,每个编译器都会指定一个随机数引擎为default_random_engine类型,它具有最常用的特性。
 
随机数引擎操作:
notion image
通常,随机数引擎的输出不能直接使用,因为生成的随机数的值范围与我们需要的通常不符,而正确转换随机数范围是极其困难的,因此称之为原始随机数。
🍅 命名空间
type
status
date
slug
summary
tags
category
icon
password
Property
🍅
目录

 
大的项目中通常需要用到第三方库,这些库通常都会定义一个名称空间,没有定义名称空间而直接使用的名字会带来名称空间污染,C 语言通过将库的名字作为函数等全局名字的前缀来避免此问题。C++则提供了名称空间,名称空间可以更有效的更好的管理名字。名称空间将全局名称空间进行切分,每个名称空间就一个作用域。
 

名称空间定义

名称空间中包含一系列的声明和定义,这些声明和定义必须是可以出现在全局作用域中的:类、变量(以及初始值)、函数以及其定义、模板和其它名称空间。
与任何名字一样,名称空间的名字必须在其作用域中是唯一的。名称空间可以定义在全局作用域中或者在别的名称空间中,但不能在函数或者类中。命名空间定义时最后的分号可有可无。
 
每个名称空间是一个作用域
🍅 不可移植的特性
type
status
date
slug
summary
tags
category
icon
password
Property
 
🍅
目录

 
为了支持底层编程(low-level programming)C++ 定义了一些固有不可移植的特性(nonportable features)。不可移植的特性是特定于机器的,使用了不可移植的特性通常需要在换了平台时重新对这部分进行编程。算术类型的长度在不同机器之间不一样就是一个不可移植的特性。
 

位域

类可以将数据成员定义为位域(bit-field),位域包含特定的二级制位数,它们通常用于传递二进制数据给另外一个程序或者给硬件设施。位域的内存布局是与机器相关的。
位域必须是整数类型或者枚举类型。通常使用的类型是unsigned类型,这是由于signed位域的行为是由具体实现决定的。通过在成员名后加冒号和常量表达式指定成员所占的二进制位数:
位域可能被会打包到一个整数值中去以压缩存储,至于是如何实现的标准并没有规定。地址操作符(&)不能用于位域字段,所以位域字段是没有指针的。
🍅 包装器
type
status
date
slug
summary
tags
category
icon
password
Property
 
🍅
目录

 

function包装器

  • 将可调用对象的类型进行统一,便于对其进行统一化管理
  • 包装后明确了可调用对象的返回值和形参类型,更加方便使用者使用
 
func可能是什么呢?那么func可能是函数名?函数指针?函数对象(仿函数对象)?也有可能是lambda表达式对象?所以这些都是可调用的类型!如此丰富的类型,可能会导致模板的效率低下!为什么呢?
编译器
type
status
date
slug
summary
tags
category
icon
password
Property
 
我们平时说的程序,是指双击后就可以直接运行的程序,称为可执行程序(Executable Program)。在 Windows 下,可执行程序的后缀有 .exe 和 .com(.exe 比较常见);在类UNIX系统(Linux、Mac OS等)下,可执行程序没有特定的后缀,系统根据文件的头部信息来判断是否是可执行程序。
 
可执行程序的内部是一系列计算机指令和数据的集合,它们都是二进制形式的,CPU 可以直接识别,毫无障碍;但是对于程序员,它们非常晦涩,难以记忆和使用。这就倒逼程序员开发出了编程语言,提高自己的生产力,例如汇编、C语言、C++、Java、Python、Go语言等
 
C语言代码由固定的词汇按照固定的格式组织起来,简单直观,程序员容易识别和理解,但是对于CPU,C语言代码就是天书,根本不认识,CPU只认识几百个二进制形式的指令。这就需要一个工具,将C语言代码转换成CPU能够识别的二进制指令,也就是将代码加工成 .exe 程序;这个工具是一个特殊的软件,叫做编译器(Compiler)
编译器能够识别代码中的词汇、句子以及各种特定的格式,并将他们转换成计算机能够识别的二进制形式,这个过程称为编译(Compile)
编译器还有一个优势。一般而言,不同CPU制造商使用的指令系统和编码格式不同。例如,用Intel Core i7 CPU编写的机器语言程序对于ARM Cortex-A57 CPU而言什么都不是。但是,可以找到与特定类型CPU匹配的编译器。因此,使用合适的编译器或编译器集,便可把一种高级语言程序转换成供各种不同类型 CPU 使用的机器语言程序。一旦解决了一个编程问题,便可让编译器集翻译成不同 CPU 使用的机器语言。
 
C语言的编译器有很多种,不同的平台下有不同的编译器,例如:
主流桌面操作系统:
  • Windows 下常用的是微软编译器(cl.exr),它被集成在 Visual Studio 或 Visual C++ 中,一般不单独使用
编程机制
type
status
date
slug
summary
tags
category
icon
password
Property
 

源文件

用C语言编写程序时,编写的内容被储存在文本文件中,该文件被称为源代码文件。大部分C系统,都要求文件名以.c结尾。在文件名中,点号(.)前面的部分称为基本名,点号后面的部分称为扩展名,基本名与扩展名的组合就是文件名。文件名应该满足特定计算机操作系统的特殊要求。例如,MS-DOS是IBM PC及其兼容机的操作系统,比较老旧,它要求基本名不能超过8个字符。有些UNIX系统限制整个文件名不超过14个字符,而有些UNIX系统则允许使用更长的文件名,最多255个字符。Linux、Windows和Macintosh OS都允许使用长文件名。
 
每种编程语言的源文件都有特定的后缀,以方便被编译器识别,被程序员理解。源文件后缀大都根据编程语言本身的名字来命名
  • C语言源文件的后缀是.c
  • C++语言源文件的后缀是.cpp
  • Java 源文件的后缀是.java
  • Python 源文件的后缀是.py
  • JavaScript 源文件后缀是.js
源文件其实就是纯文本文件,它的内部并没有特殊格式。后缀仅仅是为了表明该文件中保存的是某种语言的代码,这样程序员容易区分,编译器也更加容易识别,它并不会导致该文件的内部格式发生改变。
 
C语言标准
type
status
date
slug
summary
tags
category
icon
password
Property
 
 
 
notion image
C语言发展之初,并没有所谓的C标准。1987年,布莱恩·柯林汉(Brian Kernighan)和丹尼斯·里奇(Dennis Ritchie)合著的The C Programming Language(《C语言程序设计》)第1版是公认的C标准,通常称之为K&R C或经典C。特别是,该书中的附录中的“C语言参考手册”已成为实现C的指导标准。例如,编译器都声称提供完整的K&R实现。虽然这本书中的附录定义了C语言,但却没有定义C库。与大多数语言不同的是,C语言比其他语言更依赖库,因此需要一个标准库。实际上,由于缺乏官方标准,UNIX实现提供的库已成为了标准库。
 

ANSI/ISO C标准

随着C的不断发展,越来越广泛地应用于更多系统中,C社区意识到需要一个更全面、更新颖、更严格的标准。鉴于此,美国国家标准协会(ANSI)于 1983 年组建了一个委员会(X3J11),开发了一套新标准,并于1989年正式公布。该标准(ANSI C)定义了C语言和C标准库。国际标准化组织于1990年采用了这套C标准(ISO C)。ISO C和ANSI C是完全相同的标准。ANSI/ISO标准的最终版本通常叫作C89(因为ANSI于1989年批准该标准)或C90(因为ISO于1990年批准该标准)。另外,由于ANSI先公布C标准,因此业界人士通常使用ANSI C。在该委员会制定的指导原则中,最有趣的可能是:保持 C的精神。委员会在表述这一精神时列出了以下几点:
  • 信任程序员
  • 不要妨碍程序员做需要做的事
  • 保持语言精练简单
  • 只提供一种方法执行一项操作
C程序结构
type
status
date
slug
summary
tags
category
icon
password
Property
 
 
 

#include指令和头文件

#include <stdio.h>的作用相当于把stdio.h文件中的所有内容都输入该行所在的位置,实质是一种“拷贝-粘贴”的操作。 include 文件提供了一种方便的途径共享许多程序共有的信息。#include这行代码是一条C预处理器指令。通常,C编译器在编译前会对源代码做一些准备工作,即预处理。 所有的C编译器软件包都提供stdio.h文件。该文件中包含了供编译器使用的输入和输出函数(如 printf())信息。该文件名的含义是标准输入/输出头文件。通常,在C程序顶部的信息集合被称为头文件(header)。 在大多数情况下,头文件包含了编译器创建最终可执行程序要用到的信息。例如,头文件中可以定义一些常量,或者指明函数名以及如何使用它们。但是,函数的实际代码在一个预编译代码的库文件中。简而言之,头文件帮助编译器把你的程序正确地组合在一起。 ANSI/ISO C规定了C编译器必须提供哪些头文件。有些程序要包含stdio.h,而有些不用。特定C实现的文档中应该包含对C库函数的说明。这些说明确定了使用哪些函数需要包含哪些头文件。例如,要使用printf()函数,必须包含stdio.h头文件。省略必要的头文件可能不会影响某一特定程序,但是最好不要这样做。
注意 为何不内置输入和输出 原因之一是,并非所有的程序都会用到I/O(输入/输出)包。轻装上阵表现了C语言的哲学。正是这种经济使用资源的原则,使得C语言成为流行的嵌入式编程语言。#include中的#符号表明,C预处理器在编译器接手之前处理这条指令。
 

main()函数

C程序一定从main()函数开始执行(目前不必考虑例外的情况)。除了main()函数,可以任意命名其他函数。
圆括号有什么功能?用于识别main()是一个函数。 int是main()函数的返回类型。这表明main()函数返回的值是整数。返回到哪里?返回给操作系统。 通常,函数名后面的圆括号中包含一些传入函数的信息。该例中没有传递任何信息。因此,圆括号内是单词void。 如果浏览旧式的C代码,会发现程序以如下形式开始:
🍇 关键字和保留标识符
type
status
date
slug
summary
tags
category
icon
password
Property
 
 
 
关键字是C语言的词汇。它们对C而言比较特殊,不能用它们作为标识符(如,变量名)。许多关键字用于指定不同的类型,还有一些关键字用于控制程序中语句的执行顺序。在表 2.2 中所列的C语言关键字中,粗体表示的是C90标准新增的关键字,斜体表示的C99标准新增的关键字,粗斜体表示的是C11标准新增的关键字。
notion image
 
🍇 常量
type
status
date
slug
summary
tags
category
icon
password
Property
 
 
有些数据类型在程序使用之前已经预先设定好了,在整个程序的运行过程中没有变化,称为常量(constant);在程序运行期间可能会改变或被赋值,称为变量(variable)
 
有时,在程序中要使用常量,例如计算圆的周长:
这里3.14159代表常量pi()。在该例中,输入实际值便可使用这个常量。这种情况使用符号常量(symbolic constant)会更好,也就是说计算机稍后会用实际值完成替换:
 
 
如何创建符号常量?
方法之一是声明一个变量,然后将该变量设置为所需的常量: