c/c++语言
文章平均质量分 71
在嵌入式软件开发中,c/c++是主流语言,也是在此领域的立根之本,因此本栏将记录和分享c/c++语言的基本语法,以及常用的、提升的编程技巧。
mybright_
这个作者很懒,什么都没留下…
展开
-
Makefile基础
本文总结了makefile的概念及基础语法,不涉及makefire的内置函数。比较简单,是阅读、编写makefile基础。 1、makefile可以理解为是一门新的脚本语言,或者是一种工具,它专门用于编译:项目越庞大,代码文件越多,越能体现makefile的功能之强大。 2、makefile作为一门脚本语言,所以自然是属于解析型语言。解析型语言由解析器去解析成计算机所能识别的二...原创 2017-12-16 16:40:08 · 1390 阅读 · 0 评论 -
编写简单通用makefile
在Makefile基础中总结了makefile最常用的基础,利用这些知识点,足矣编写通用makefile运用于c/c++项目中。本文基于这样的文件编写makefile: 编写makefile需要实现: (1) 将bank.cpp编译成静态库bank.a/动态库bank.so; (2) 将bank.a和bank.so拷贝/opt/lib目录下; (3) 将bank.h拷贝原创 2017-12-16 21:57:51 · 1353 阅读 · 0 评论 -
单向链表(c++实现)
在顺序表(c++实现)一文中讲到,顺序表是基于顺序存储结构的数据结构,即用一段地址连续的存储单元依次存储数据元素,与之相对的另一种线性表–链表,它则是基于链式存储结构的数据结构:数据元素除了存储本身的信息之外,还需要存储器直接后继(和前驱)的信息,前者是数据域,后者是指针域。 线性表共有的操作,封装在List类中://List.h#ifndef __LIST_H__#define _原创 2018-01-29 18:38:03 · 1648 阅读 · 0 评论 -
循环单向链表(c++实现)
在单向链表(c++实现)中,链表的最后一个节点的nex指针指向NULL,而所谓的循环单向链表即是指链表的最后一个节点的next指针指向首节点(注意不是头节点,头节点是方便链表操作而存在的结构体变量)。循环链表是一种特殊的单向链表,因此软件设计上,循环链表可继承自单向链表。 循环单向链表的实现难点在于: (1)插入数据的位置为0时,头节点和尾节点的next指针均指向新节点; (2)原创 2018-02-02 18:06:17 · 3864 阅读 · 0 评论 -
双向链表(c++实现)
单向链表的缺点:逆序访问单向链表中的数据元素,效率低下。 若从头节点开始依次访问单向链表的元素,可使用m_current游标,但是逆序访问,只能通过下面代码实现访问:int main(void){ LinkListint> ll; for (int i = 0; i 6; ++i) //O(n) { ll.insert(0, i); }原创 2018-02-02 18:14:36 · 4138 阅读 · 0 评论 -
offsetof和container_of
背景:在项目中,我将设备的配置信息封装在一个结构体中,并用一个unsigned int的变量上的某些位标志来对应某些配置项,该结构体需要被保存在本地配置文件中,程序启动时需要加载配置文件上记录的该结构体的配置信息,若不存在则将该结构体默认配置信息写入文件。在程序运行期间,若用户改变了某些配置,标志变量对应的标志位被置1,程序在得知发生变化的标志量后就将对应的配置信息更新到配置文件中。 假设原创 2018-02-04 17:00:29 · 596 阅读 · 0 评论 -
移植Linux内核链表
Linux内核源码中的链表是一个双向循环链表,该链表的设计具有优秀的封装性和可扩展性。本文将从2.6.39版本内核的内核链表移植到Windows平台的visual studio2010环境中。链表的源码位于内核源码的include/linux/list.h中。移植的步骤如下: (1)去除依赖的头文件 list.h依赖的头文件如下:#include <linux/typ...原创 2018-02-07 16:53:13 · 921 阅读 · 0 评论 -
栈(c++实现)
栈是一种特殊的线性表, 线性表是具有相同类型的n(n>=0)个数据元素的有序(中间不能空位置)有限序列。 对栈的操作(增/删/读)只能通过栈的一端进行,允许操作的一端称之为栈顶,不允许操作的一端称为栈底。栈的特性为先进后出。c++实现栈,可采用如下的设计思路: Stack是一个接口类,封装了栈的所有操作://Stack.h#ifndef __STACK_H...原创 2018-03-01 10:57:31 · 11448 阅读 · 1 评论 -
队列(c++实现)
队列的特点是先进先出,跟栈的c++实现类似,队列的c++实现同样有两种方式: Queue是一个接口类,封装了队列相关的所有操作://Queue.h#ifndef __QUEUE_H__#define __QUEUE_H__#include <exception>template<typename T>class Queue{public:...原创 2018-03-01 14:41:28 · 1345 阅读 · 0 评论 -
gdb调试的常用命令
gcc a.c b.c -o app -g -g:会保留函数名和变量名于app中1、 启动gdb调试功能 (1)gdb app (2)给程序传参:set args xx1 xx22、 查看代码(list/l) (1)查看当前文件:ll 行号l 函数名(2)查看非当前文件:l 文件名:行号l 文件名:函数名(3)设置显示的行数set ...原创 2018-03-15 10:12:44 · 623 阅读 · 0 评论 -
使用VisualStudio2017开发Linux/c++程序(上)
环境 Windows10_x64 CentOS7_64(虚拟机)1、 Windows系统中安装VisualStudio2017 2、 Linux系统中安装gcc、g++和gdbserver 3、 创建Linux/c++项目 3.1创建app_test解决方案 3.2 添加新建项目main 这样vs2017会自动生成main.cpp文件。点击“生成”-...原创 2018-05-11 18:01:46 · 6499 阅读 · 3 评论 -
使用VisualStudio2017开发Linux/c++程序(下)
基于前面的环境及工程构建解决方案:主程序 + 静态库 + 动态库,并在主程序中调用静态库和动态库的函数。(参照文章https://www.cnblogs.com/dongc/p/6599461.html和http://www.mamicode.com/info-detail-1983443.html)一、创建解决方案1、右键解决方案->添加->新建项目 2、 右键stat...原创 2018-05-14 11:48:11 · 4359 阅读 · 3 评论 -
实现智能指针
c/c++中内存的动态分配的结果是一个指针,该指针指向该片堆内存空间。c/c++中并没有垃圾回收机制,而用户使用完该堆空间后又可能忘记释放该片堆内存空间,这就造成内存泄漏。一个行之有效的解决办法就是采用智能指针代替原始指针,弥补原生指针无法控制所指堆空间的生命期的空缺。 在c++11标准中有多个智能指针,其中包括共享指针shared_ptr和独占指针unique_ptr。本文将实现Share原创 2018-02-02 12:47:22 · 477 阅读 · 0 评论 -
派生类向基类的自动类型转换
在c++中,派生类向基类的自动类型转换只对指针或引用有效,在派生类对象和基类对象之间不存在这样的转换。将一个派生类对象初始化和赋值给一个基类对象,事实上调用的是基类的拷贝构造函数和赋值操作符重载函数,因为这两个函数的参数是基类类型的const引用,所以还是基于引用的自动类型转换。 派生类向基类的自动类型转换时c++类继承的难点之一,能力有限,先尝试表达自己的看法。转换操作主要发生在: (1)原创 2017-12-23 21:30:11 · 2207 阅读 · 0 评论 -
顺序表(c++实现)
线性表是具有相同类型的n(n>=0)个数据元素的有序(中间不能空位置)有限序列,如: X0, X1, … Xn-1 其中Xi为表项,n为长度。线性表具有如下性质: (1)线性表的首元素X0,只有一个后继。 (2)Xn-1为线性表的最后一个元素,只有一个前驱。 (3)除X0和Xn-1外的其它元素既有前驱又有后继。 (4)支持逐项(下标)访问和顺序存取。原创 2018-01-12 23:37:31 · 830 阅读 · 0 评论 -
数组类(c++实现)
用c++实现数组类以代替原生数组,数组类可以包含数组的长度信息,主动发现访问越界,通过操作符重载还可以实现数组间的赋值赋值操作。类似于之前的线性表,数组类Array为一个抽象模板,数组的存储空间的分配和大小的指定均在子类实现。 数组空间由静态分配所得代码示例://Array.h#ifndef __ARRAY_H__#define __ARRAY_H__#include #inc原创 2018-01-16 22:38:34 · 3682 阅读 · 0 评论 -
简易内存池的实现
最近在实现一个静态链表,即链表的节点占据的空间并非等到插入时再在堆空间中动态分配,而是在一块我们预先分配好的内存空间(可以在栈也可以在堆上)中找出一块空闲的内存空间来使用,当要销毁给节点时,不是delete掉该空间而是将该空间置为空闲标志。这就是池的思想,内存池、线程池的核心思想也是如此。池的设计考虑到许多内存管理技巧,本文只是记录自己的一些简单的笔记。 定义模板类MemPoolManage原创 2018-01-29 18:09:34 · 521 阅读 · 0 评论 -
c++箭头操作符(->)重载函数
箭头(->)操作符是个二元操作符,其左操作数是类对象的地址或者是重载了箭头运算符的类对象,右操作数是类的成员。箭头操作符重载函数只能是类的成员函数(参考为什么有的操作符重载函数只能是成员函数?)。 箭头运算符的使用方法为:obj->mem; obj->func(); obj为某个类对象的地址,mem和func()分别是该对象的成员变量和成员函数,这样的用法是我们之前学原创 2018-01-06 15:29:14 · 3197 阅读 · 0 评论 -
组合按键的软件设计(c语言)
需求: 根据用户的四个按键的(上下左右)显示对应的内容,左右键切换显示项目名称,上下键切换切换该项目的具体信息条目。另外有一个无符号整型变量上的每一位用于控制项目的显示与否,该位为1则显示对应项目,反之则不显示该项目。 组合按键采用面向对象的思想,加上数据结构中的双向链表,这样的组合按键需求十分容易实现。 下面是对上述需求的模型化: Linux终端用于显示,键盘上的w、s、a、原创 2017-12-28 18:37:41 · 4801 阅读 · 0 评论 -
派生类覆盖基类的重载的函数
和其他函数一样,类的成员函数不论是否是虚函数都可以被重载(重载的发生需要是在同一作用域)。然而,派生类一旦声明了一个和基类重载函数同名的函数,派生类将会覆盖基类的所有重载函数,也就是说派生类可以覆盖基类重载函数的0个或全部个实例。 如下代码:class Base{public: void func() { printf("Base func()\n"); }; void fun原创 2017-12-24 15:42:34 · 6581 阅读 · 3 评论 -
c++类的不同继承方式
c++类中成员有3种访问属性:public、private和protected,派生类对基类的继承方式同样是这3种。c++类对一个继承而来的成员的访问权限受两个因素影响: (1) 该成员在基类中的访问权限说明符 (2) 派生类的继承方式 需要注意,上述是站在一个派生类的使用者(包括继承该派生类的新派生类)而言的。所站在派生类的实现者而言,他对继承而来的成员的访问权限只是上述的第一点,即原创 2017-12-23 15:53:50 · 7440 阅读 · 0 评论 -
c++单例模式类模板的实现
设计模式中的单例模式有懒汉单例模式和饿汉单例模式两种,这部分内容记录在http://blog.csdn.net/qq_29344757/article/details/75575217中。 懒汉单例模式的设计步骤为: (1) 将构造函数的访问属性设置为private,不让该类中外部生成对象 (2) 将标志指针变量初始化为NULL (3) 当外部需要使用对象时,调用类的静态成员函数,该函数判断原创 2017-08-20 18:37:49 · 5638 阅读 · 7 评论 -
c++类的二阶构造
c++类的二阶构造函数主要适用于在构造函数申请系统资源的场景。普通构造函数的作用是初始化对象,若在初始化过程中不能按照程序员预期的进行,那么将会得到一个半成品对象。以下面代码为例:using namespace std;class SecondOrder{private: char* pchar; int val;public: SecondOrder() {原创 2017-09-07 11:00:55 · 2234 阅读 · 0 评论 -
中缀表达式转后缀表达式
栈的使用场景之一,中缀表达式转为后缀表达式。 将中缀表达式拆分成各个数字和运算符,并去除了括号,存到数组(或者容器、队列)中,遍历之:若是数字,直接存放到用于输出的数组(或者容器、队列)中若是”(“压栈若是”)”持续出栈,直至出栈的是”(“或者栈为空(括号不输出,直接丢弃)若是加减乘除运算符,则与栈顶运算符比较,当前运算符若大于栈顶运算符,则将当前运算符入栈;当前运算符若小于等于栈顶运算符原创 2017-09-07 17:00:13 · 465 阅读 · 0 评论 -
当c++中的联合体遇到类的构造函数
在学习Qt的QVariant时,Qt Create的说明手册中说道:Because C++ forbids unions from including types that have non-default constructors or destructors, most interesting Qt classes cannot be used in unions. 大概意思是:因为c++禁原创 2017-09-22 10:29:33 · 4210 阅读 · 2 评论 -
数据结构概念解析
1. 什么是数据结构 计算机软件是为了解决现实生活中的问题而存在的,生活中的不同个体体现在软件中即是“数据”。生活中的不同个体间势必存在某些联系,所以在软件设计中需要用某种逻辑来表现这些关系,这就是数据结构。 计算机的“数据”有3个重要概念: 数据元素:组成“数据”的基本单元 数据项:一个数据元素由若干个数据组成 数据对象:性质相同的数据元素的集合 听起来比较抽象,可以用“人原创 2017-10-14 16:19:32 · 425 阅读 · 0 评论 -
实现通用的双向链表(c语言实现)
国庆8天在家阅读李先静大神的书籍,抽空把一些笔记记录下来。从实现一个通用的双向链表开始。1. 构建链表节点 链表节点存值还是存值的地址(指针)?对于通用链表首先要做到能够存放任何数据类型的数据,首先可能会想到的是union,但是数据类型无穷无尽,不可能在union中全部表示。那么可行的办法有两种: (1) 存值typedef struct _DListNode DLis原创 2017-10-16 15:46:08 · 8317 阅读 · 3 评论 -
c++有序关联容器中键类型的约束
本文以map为例来解释有序关联容器中键类型的约束。 map是键-值对的集合,可以理解为关联数组: std::map<int, string> map1;map1.insert(make_pair<int, string>(4, "linux"));map1.insert(make_pair<int, string>(2, "c/c++"));map1.insert(make_pair<int原创 2017-12-02 17:29:05 · 482 阅读 · 0 评论 -
程序中数据存放的位置
基本上程序员在开始接触Linux编程时就大抵就都听过代码段、数据段等等概念,它们是各种数据存放的位置。通过objdump -h命令可以查看一个.o文件(已编译成二进制文件但未链接)的各个段:1. 代码段(.txt) .txt段存放代码(如函数)与部分整数常量,.txt段的数据可以被执行2. 数据段(.data) .data用于存放初始化过的全局变量。若全局变量值为0原创 2017-10-16 17:30:50 · 4104 阅读 · 0 评论 -
c++赋值兼容规则
赋值兼容规则是指在需要父类对象的地方可以使用子类对象来代替: 通过public继承,子类得到了父类除构造/析构函数之外的所有成员,且所有成员的访问属性和父类的完全相同。这样,public继承的子类实际就具备了父类的所有功能,凡是父类能解决的问题,子类都可以解决。 赋值兼容规则是发生在父类和子类之间的: (1) 子类的对象可以赋值给父类对象对象,过程会发生隐式类型转换 (2) 父类类型原创 2017-11-11 09:03:17 · 3656 阅读 · 0 评论 -
c++ this指针与const对象
在 c++的const对象一文中已经介绍了const对象的属性,本文尝试从this指针的角度,再来分析const对象。1. 问题引入 同样的示例,定义一个类,并将其实例化为const对象://1_const_obj.cppclass Obj{private: int pri_dat;public: int get_pri_dat() {原创 2017-11-16 18:38:38 · 1492 阅读 · 0 评论 -
为什么有的操作符重载函数只能是成员函数?
出自于c++ primer 5e的一句话: 赋值(=)、下标([])、调用(())和成员访问箭头(->)运算符必须是成员(函数)。 为什么?对于赋值运算符来说,我们知道一个c++类,程序员如果没有为其定义了赋值操作符重载函数,编译器也会隐式的定义,这样倘若再定义全局赋值运算符重载函数,将会发生二义性。即使编译器允许这样的定义手法,在调用的时候也编译不过:cls& operator=(cls&原创 2017-12-16 15:32:45 · 11637 阅读 · 4 评论 -
c++的typeid关键字
1. typeid关键字的引入 回顾c++的赋值兼容性原则,子类的对象在使用上可以被当做基类的对象,反过来则不可。具体表现在: (1) 子类的对象可以被赋值给基本对象 (2) 指向基类的指针可以指向子类 (3) 子类的对象可以初始化基类对象的引用class BaseCls{public: //... virtual ~BaseCls() {}};cla原创 2017-08-24 12:48:25 · 885 阅读 · 0 评论 -
c++的异常处理
1. c++的异常处理介绍 c++的异常处理语法:int main(void){ try { double a = div(6, 0); } catch(...) { printf("div 0 is error!!\n"); } return 0;} 如上try…catch两个语句块,将正常功能代原创 2017-08-21 00:04:26 · 408 阅读 · 0 评论 -
c++的类模板
泛型思想可运用于函数即函数模板外,还可以运用于类即模板类,使得类的实现不关注数据元素的具体类型,而只关注类所需要实现的功能。模板类在实际中主要用于存储和组织数据元素,如数组类、链表类、栈类(后进先出)、队列类(先进先出)等,这些类的共同之处为:类中的数据组织方式和数据元素的具体类型无关。 模板类的语法如下:template<typename T>class TestCls{public:原创 2017-08-20 01:51:25 · 591 阅读 · 0 评论 -
为什么把c++类的析构函数声明为虚函数?
如题,当一个类为基类的时候,通常其析构函数被声明为虚函数,这是为啥?class BaseCls{public: BaseCls() { printf("BaseCls()\n"); } ~BaseCls() { printf("~BaseCls()\n"); } void test_func() {原创 2017-08-18 23:47:29 · 567 阅读 · 0 评论 -
c++中抽象类和接口
1. 抽象类 在面向对象编程中,抽象类是一种只能定义类型,不能生成对象的类,它是对一系列看上去不同,但是本质相同的具体概念的抽象。最典型的的抽象类就是”图形”,三角形、矩形、梯形都是图形,它们都具有边长、面积属性,”图形”类是对这系列的抽象。 程序设计中,我们可以定义一个表征图形的类,然后具体图形继承该类。图形类,即基类定义如下:class Shape{public: double ar原创 2017-08-18 00:17:10 · 11069 阅读 · 7 评论 -
c++的函数模板
可以这么说,泛型编程是面向对象编程最为强大的编程方式,它是一种不考虑具体数据数据类型的编程方式。c++的泛型编程有函数模板和类模板,先来看看函数模板。1. 函数模板的引入 以交换值为例:我们要交换int型、char型和double型的两值,需要写3个函数:void swap(int& a, int& b){ a ^= b; b ^= a; a ^= b;}void sw原创 2017-08-19 01:17:34 · 545 阅读 · 0 评论 -
c++多态的实现原理
c++多态的实现,依靠的是虚函数表。先来看看代码:#include <iostream>using namespace std;class TestCls{public: int a; void func() { cout << "hello" << endl; }};int main(void){ cout << "sizeof(Te原创 2017-08-17 23:09:23 · 281 阅读 · 0 评论 -
c++的多态
1. 子类父类中同名成员的冲突问:子类中是否可以定义父类中的同名成员变量?class BaseCls{public: int a; void BasePrint() { std::cout << "Base::a = " << a << std::endl; } };class SubCls : public BaseCls{public:原创 2017-08-14 12:48:49 · 450 阅读 · 0 评论