C/C++
墨篙和小奶猫
车联网以及嵌入式开发 优化理论 故障诊断
展开
-
C语言:宏定义的#和##用法
在查看学习操作系统的过程,会经常遇到各种宏定义,其中有两种宏参数的定义方式较为特殊,分贝是#和##。 其中#为将宏参数按照符号名直接解析成字符串;##为参数连接符号。#include <stdio.h>#include <string.h>#include <climits>#define STRCPY(a,b) strcpy(a##_p, #b) //把第一参数后边加上字符_p,把第二个参原创 2017-10-21 17:22:18 · 1421 阅读 · 0 评论 -
STL工具库使用解析系列之二:自定义比较函数的两种方式(重载和仿函数)
C++比C不仅多了面向对象支持class类编程,还支持泛型编程,以及提供丰富的STL开发工具库。泛型是一种在编译期间动态具体化的技术,使得一些通用算法或数据结构的封装变得十分方便。在C++标准中指出,当一个模板不被使用时,它就不应该被具体化。对于模板在编译期间如何特化,其实用到的概念诸多,比如“惰性求值”和“模式匹配”,两点关键: 1.对于函数模板: 确定特化的参数类型是隐式传进去的,编译器将根原创 2017-11-27 22:50:54 · 869 阅读 · 0 评论 -
杂货边角(14):C++11在构造函数方面的新特性
C++中类是面向对象编程的基础,但是一旦类的属性域很多时,必然面临着构造函数的数量爆炸,并且各个构造函数可能只存在局部的细节差异,故而为了应对这种存在明显代码段重复的情况,违背了代码重复即原罪的原则。C++11针对构造函数存在的代码臃肿问题专门引入了继承构造函数机制和委托构造函数机制,前者是用来针对子类和父类中的构造函数的重复问题,后者是针对本类中多个构造函数间差异微小导致的代码重复问题。目录:Se原创 2018-02-05 15:23:04 · 271 阅读 · 0 评论 -
杂货边角(11):C++11之lambda匿名函数
匿名函数lambda思想是函数式编程的基础,其中以lisp为代表,以其抽象和迭代的思想让无数coder奉为圣经。函数式编程、命令式编程、面向对象编程、元编程等都是一种编程范型。而近年来的趋势是高级语言越来越多地引入多范型编程支持(如C++和Python都开始支持函数式编程)。C++11引入lambda特性,对于泛型编程和函数式编程的支持都极大提升。相比于lisp的lambda函数等同于C++98中的原创 2018-01-30 11:06:35 · 381 阅读 · 0 评论 -
杂货边角(23):模板编程的SFINAE机制和enable_if使用
SFINAESFINAE全称:Substitution Failure is not an error.即在对模板函数调用进行实例化推导匹配时出现的无效函数将被删除,并且编译器不会报错,只有最终有一个可以匹配该次调用的实例化match即可。在对一个函数调用进行模板推导时,编译器会尝试推导所有的候选函数(模板、重载函数、普通函数),并最终结合偏特化原则,给出一个最好的匹配结果。如果在推导的过程中,出现原创 2018-02-26 16:26:31 · 530 阅读 · 0 评论 -
杂货边角(15):C++11引入的explicit显式转换控制
C++此前编译器默认的隐式类型转换机制,在解决程序的泛型应用上起到了不小的帮助,但是这种隐式的类型转换有可能会导致潜在的问题。举代码如下#include <iostream>using namespace std;struct Rational_1 { Rational_1(int n=0, int d=1) : num(n), den(d) { cout << __func原创 2018-02-12 16:54:27 · 646 阅读 · 0 评论 -
杂货边角(16):C++11之后,类的所有构造函数
C++类声明中,编译器会默认帮助程序员生成一些他们未定义的成员函数,这样的函数被称为“默认函数”,这包括了以下一些自定义类型的成员函数: 1.构造函数; 2.拷贝构造函数 3.拷贝赋值函数(operator= (const Class & T) ) 4.移动构造函数 5.移动拷贝赋值函数(operator= (Class&& T) ) 6.析构函数 但是程序员一旦在类的定义中显式地声明原创 2018-02-12 17:07:05 · 221 阅读 · 0 评论 -
杂货边角(17):C++11的右值引用和移动语义
相信绝大多数人,在写C++代码时都会被函数返回值的多次传递弄混淆过。事实上,这涉及到堆栈的运行,对于一个子函数而言,除非程序员显式地调用new操作符,否则函数创建的对象只能在自己的临时栈上,子函数和父函数的临时栈不同,从而这必然存在多次传递的情况。以前在C++标准没有涉及到该问题时,都是编译器自作主张地进行优化,即所谓的RVO(return value optimization),但是编译器提供的R原创 2018-02-12 18:33:18 · 275 阅读 · 0 评论 -
杂货边角(24):C++智能指针和垃圾回收
目录:Sec1 C C98的显式内存管理的不足Sec2 C11的智能指针Sec3 垃圾回收机制Sec1. C / C++98的显式内存管理的不足内存管理和垃圾回收是高级语言的重要特征,尤其是随着代码抽象程度的加深,C以及C++98将内存管理完全交给程序员的做法一直是让人诟病的地方,即在堆上显式地通过malloc/free或new/delete来管理所需内存。但是是人就一定会犯错,原创 2018-02-27 15:47:02 · 1210 阅读 · 0 评论 -
杂货边角(25):完美转发
完美转发是C++11借助右值引用这个引入的特性而顺带完成的一个很美的特性,涉及到两个重要的概念:引用折叠和模板参数推导。#include <iostream>#include <type_traits>using namespace std;void RunCode(int && m ) { cout << "rvalue ref" << endl; }void RunCode(int & m原创 2018-02-28 18:40:06 · 270 阅读 · 0 评论 -
杂货边角(26):强枚举类型enum class
枚举类型是C++从C继承而来的特性,但是枚举类型在C中的实现其实和宏无差别,即#define Male 0#define Female 1....//用枚举声明为enum {Male, Female}这种枚举类型和int整数的天然等价性很容易造成一些漏洞,如不同枚举名字域下的比较,并且传统的枚举类型中的符号是直接开发在父作用域中,这也容易导致符号冲突。而C++11引入的强枚举类型,非常好理解原创 2018-02-28 18:48:30 · 665 阅读 · 0 评论 -
杂货边角(18):POD类型
POD英文全称为Plain Old Data。是C++为了保持和C的兼容性而提出的一个重要概念,该种数据的最主要特征是可以使用memcpy(), memset()等传统的函数直接对数据内存进行字节级别操作。C++11从两个方面来判断一个数据类型是否是POD的。考虑到C++语言自带的数据类型往往都是直接继承自C的,故而完全可以默认为POD的,而C++相比于C在数据结构方面最大的多样性来源,便是用户自定原创 2018-02-25 09:00:38 · 280 阅读 · 0 评论 -
杂货边角(19):explicit显式类型转换限定符号
#include <iostream>using namespace std;struct Rational_1 { Rational_1(int n=0, int d=1) : num(n), den(d) { cout << __func__ << "(" << num << "/" << den << ")" << endl; } int num; /原创 2018-02-25 09:34:32 · 291 阅读 · 0 评论 -
杂货边角(20):匿名非受限联合体实现类的“变长成员”variant member
#include <iostream>#include <cstring>using namespace std;/*联合体的使用,最主要的效果便是内存空间的节省,当然额外的附加作用便是灵活性,但是这种灵活性是以牺牲可读性为代价的*/union T { string s;//因为string 是非POD类型,string有non-trivial的构造函数,故而系统会删除T的默认构造原创 2018-02-25 10:09:31 · 465 阅读 · 0 评论 -
杂货边角(21):用户自定义字面量 operator "" _X
在C++编程中,用户自定义类或结构体是难以避免的事情,所以一旦遇到接受用户自定义的类或结构体作为参数的函数,那么必然难逃”先初始化变量–变量传值或传引用调用函数“,这就导致了编程过程中出现的不直观。struct T {...};void func(T t1, T t2) {...}...T temp1(xxxx);T temp2(xxxx);func(temp1, temp2);正所谓没有对原创 2018-02-25 15:55:03 · 388 阅读 · 0 评论 -
杂货边角(10):模板template和可变参数模板variadic template
前面说到可以通过反射机制来解放客户端对于同类型函数调用的手动分配,而将具体的定位和调用过程通过反射机制来实现,客户端输入的信息只需要是注册机中的function对应的key即可,这样可以在client程序中减少难看冗长的switch结构或if…else…结构。但是反射机制只是变相地将任务的复杂性交给了后台库的实现者,库的实现者依旧不得不挨个实现所有相似的函数个体。这里面重复的工作量可想而知,但是有什原创 2018-01-19 17:15:09 · 310 阅读 · 0 评论 -
运行库:变长(可变)参数原理
任何C语言程序要想能够得到运行,都离不开背后的一套庞大的代码来进行支持,这一套语言相关的代码便是C语言运行库CRT(C Runtime Library),某种意义上运行库可以看成是C语言的程序和不同操作系统之间的抽象层。一个C语言运行库大致包含了以下功能: /1.启动初始化与退出清理:包括入口函数及入口函数所依赖的其他函数集合; /2.标准函数:由C语言标准规定的C语言标准库所拥有的函数实现,如原创 2017-10-15 17:03:27 · 433 阅读 · 0 评论 -
杂货边角(9):C++实现事件委托机制
在设计模式中,根据耦合紧密度可以得到排序为:继承 > 依赖 > 组合/聚合 > 委托。其实个人感觉,事件委托机制说白了就是一个函数指针数组,通过注册绑定的函数,然后在特定的事件发生后触发遍历执行所有注册的函数,机制其实和C++运行库glibc中crtbegin.o和crtend.o收集当前程序中所有全局对象的初始化函数和析构函数,用以执行遍历操作一致。所以归根结底,事件委托机制的关键便是函数指针注册原创 2018-01-18 16:37:30 · 541 阅读 · 0 评论 -
出于数据保护的结构体指针强制转换和字段截断
/*人为地在更改结构体指针的类型,从而手动地实现结构体指针在读取第一个字段之后便被截断,可以用来隐藏不想暴露的其他信息*/#include <stdio.h>#include <stdlib.h>#include <string.h>void foo(){ printf("inSide foo function\n");}typedef void (* Func)();typedef原创 2017-10-21 17:53:57 · 644 阅读 · 0 评论 -
#include指令加载外部库的两种用法
C中可以通过#include <header.h>和#include "header.h"来加载文件,两者的区别主要是在include加载的搜索路径上存在不同。区别是: 采用#include <header.h>,链接器会按照系统指定目录(如Windows下给INCLUDE环境变量指定的路径顺序)去查找头文件<header.h>。采用#include "header.h"方式,链接器会先到当前目录原创 2017-11-14 21:44:57 · 2660 阅读 · 0 评论 -
杂货边角(2):AT&T和INTEL汇编语法
汇编存在多种形式,目前主流的有AT&T汇编和INTEL汇编,这两种形式极其容易混淆,其中AT&T汇编语法被Linux和GCC广泛支持,而INTEL则由Windows支持,故而对于长期涉及到两种操作系统编程的人而言,这两种汇编语法虽本质相同,但是语法形式的差异常常让人混淆。这里便介绍了两者的主要区别。 1. 赋值方向不同 INTEL汇编语法第一个操作数表示目的操作数,第二个才是源操作数,赋值方向为原创 2017-12-20 16:05:33 · 1210 阅读 · 0 评论 -
杂货边角(3):GCC内嵌汇编
前面介绍过miniCRT自定义运行库的代码中涉及到一段代码static int open(const char* pathname, int flags, int mode){ int fd = 0; asm("movl $5, %%eax \n\t" "movl %1, %%ebx \n\t" "movl %2, %%ecx \n\t"原创 2017-12-20 18:09:11 · 314 阅读 · 0 评论 -
杂货边角(5):预编译指令#家族define/pragma
编译器提供的预处理指令主要是以#作为首字符的,如本文的两个主角#define和#pragma。合理的使用预处理指令可以使得编写的程序更便于修改(#define MAX_SUM 10000)、平台兼容性(#ifdef WIN32 ... #else...#endif)和调试(#define __DEBUG)。如下的例子/*********根据操作系统不同设置不同的处理方式,以达到同样的功能效果****原创 2017-12-21 20:13:44 · 339 阅读 · 0 评论 -
杂货边角(6):Windows的数据类型和编译器固定数据类型对照
基本数据类型作为我们经常用到的东西其实经常容易被我们忽略其中的小文章,有些情况下如果没搞清楚其中的对应关系,则很容易导致我们的程序可移植性下降。short(__int16),long (__int32),long long(__int64)是编译器层面提供的规定,分别是2、4、8字节。而int 、float、double是C语言层面提供的规定,在32位程序上分别是4\4\8 Bytes,但未来随着系原创 2017-12-21 22:46:26 · 225 阅读 · 0 评论 -
STL工具库使用解析系列之一 STL::map
STL是C++提供标准模块库的缩写,其中涉及多诸多常用的数据结构和算法,本文便是介绍map结构,一种和hash-table同样使用键值对的数据结构,但和哈希表常用数组实现不同,STL::map内核数据结构是红黑树,故而相比于hash-table的搜索速度是O(1), 而STL::map搜索时间复杂度是O(LogN)。但考虑到空间复杂度和动态扩展性能,以及要设计表现优异的hash函数的难度,故而对于存原创 2017-11-27 22:36:22 · 315 阅读 · 0 评论 -
c语言系统默认宏__VA_ARGS__、__LINE__等用于高效Debug
对于涉及多文件较大规模的程序员而言,在不同地方设置printf()用于查看代码运行进展以及查看距离故障点最近位置是很有用的,但是手动地在系统中插入一个个printf(...),最终版一个个删显然太蠢了。这里介绍一个成体系的Debug函数组。#ifdef _DEBUG#define DEBUG(...) fprintf(stderr, __VA_ARGS__ ) #else#define原创 2017-12-15 17:10:42 · 1296 阅读 · 0 评论 -
杂货边角(1):计算机中有符号数和浮点数表示和运算
1. 整数的有符号表示方式 计算机中目前常用的整数类型分为int_32和int_64,以32位为例。计算机中都以补码形式存放有符号数。正整数的补码表示和正整数的无符号类型一致,符号位为0; 负整数的补码表示则需要依次经过求反码,求补码,举例如下对于-4而言,则符号位为1, 4的二进制表示为 000 0000 0000 0100求反码: 1原创 2017-12-19 16:04:03 · 1709 阅读 · 1 评论 -
杂货边角(4):C语言static, inline, volatile, const等关键字解析
1. static关键字解析 ANSI标准规定了C具有32个关键字,其中绝大多数并无特别之处,除了涉及到存储类型的几个关键字,而我们的static关键字便是属于存储类型声明的关键字一类:1. auto: 声明该变量标识符是存放在栈上的(局部变量的默认修饰符),编译器自动完成,现今不需要手动声明,故而该修饰符几乎不用; 2. register: 声明寄存器变量,我们知道变量存放在原创 2017-12-21 15:37:10 · 982 阅读 · 0 评论 -
杂货边角(7):C++继承和多态的符号表角度解析
面向对象设计核心的思想便是抽象、封装、继承、多态和接口。继承机制是面向对象设计过程中动态性和模块性的来源,而多态性则是很多功能灵活性的来源。 0. C++继承机制 面向对象设计核心是抽象的思维,但是”重复两次的代码就可能有坏味道“,如果仅仅通过抽象将不同的功能模块具象成对象,但是不同对象间很可能存在着很强的相似性,如果独立成类,必然会造成重复,这便是继承机制出现的目的:复用。不过继承虽好,但是继原创 2018-01-17 13:10:36 · 830 阅读 · 0 评论 -
杂货边角(8):C++实现反射机制
0. 反射机制是什么 最近在学习设计模式,经常能看到对反射机制的倍加推崇,如反射机制配合工厂方法模式可以有效减少逻辑判断分支存在导致不便维护的情况。所谓的反射的机制,即通过动态地字符串等输入参数为信息入口自动寻址调用相应函数的机制。比如如下场景/*****something forehead********/switch key{ case "调用SQL server数据库":原创 2018-01-17 15:03:55 · 309 阅读 · 0 评论 -
杂货边角(12):C++11动态性来源之类型推断 && auto\decltype\追踪返回类型
在程序员眼中,如果非要二元论的谈论编程语言,那么相信很多人会说出语言存在动态和静态语言之分,其中静态语言以C++、Java为代表,而动态语言则以近年来风头正盛的Python、Ruby领衔。其实语言的动静之分主要是在于对变量进行类型检查的时间点不同,对于静态语言而言,类型检查是发生在编译阶段,因为变量在.data区或者堆栈上的占用空间大小要提前确定,这样才能给予地址分配;而对于动态语言而言,变量的类型原创 2018-02-01 22:08:34 · 601 阅读 · 0 评论 -
杂货边角(13):利用可变参数模板根据函数指针得到返回值类型和形参类型
前面提到过variadic template机制最为核心的便是“递归”思想,这里通过一个比较生僻的使用案例来阐述可变参数模板,以及decltype和declval的使用示例。#include <iostream>#include <sstream>#include <type_traits>#include <typeinfo>using namespace std;class A{};t原创 2018-02-01 22:39:23 · 626 阅读 · 0 评论 -
杂货边角(22):名字空间namespace的一二事
namespace一直是C++编程中封装性的重要概念,但是关于namespace的使用此前一直并没有太多总结,这里结合namespace的使用和C++11关于名字空间的新特性总结如下。 目录:Sec1 子命名空间间的信息交互Sec2 不同名字空间下的模板类特化问题Sec3 终极一问Sec1. 子命名空间间的信息交互C++ 程序是编译器中的”符号表“结合不同的符号名修改规则来管理不同文件不同名字原创 2018-02-25 16:51:58 · 407 阅读 · 0 评论