随笔分类 - C/C++编程

摘要:该文介绍了如何使用指针中一些未使用的位来隐藏一些数据。 When we write C code, pointers are everywhere. We can make a little extra use of pointers and sneak in some extra informat 阅读全文
posted @ 2015-06-15 11:11 Mr.Rico 阅读 (341) | 评论 (0) 编辑
摘要:在Linux中关于IP和无符号整数之间的转换有两个比较好的函数: int inet_aton(const char *cp, struct in_addr *inp); char *inet_ntoa(struct in_addr in); 通过函数名就可以知道函数作用了.这里需要注... 阅读全文
posted @ 2012-10-17 23:31 Mr.Rico 阅读 (207) | 评论 (0) 编辑
摘要:现代C++程序设计比较推崇使用模板STL。STL是C++中一个非常重要的改革。在C++03之后,STL表现非常不错,STL中提供了一些常见的算法。这些算法可以直接使用,而不需要自己再去写,效率。 简单总结一下STL一些比较好的算法。 一. 非变易算法 1. for_each:遍历容器元素进行操作 该... 阅读全文
posted @ 2012-10-11 23:13 Mr.Rico 阅读 (572) | 评论 (0) 编辑
摘要:1. strspn与strcspn 2. strtok与strpbrk 3. strstr, strchr与strrchr 4. 字符串与数值之间的转换:atoi,atol,atof,strtod,strtol,strtoul 5. frexp和ldexp 1. strspn与strcspn (1)... 阅读全文
posted @ 2012-10-11 23:05 Mr.Rico 阅读 (922) | 评论 (1) 编辑
摘要:C语言中的时间相关的函数 是C标准函数库中获取时间与日期、对时间与日期数据操作及格式化的头文件。宏: NULL null是一个null指针常量的值 CLOCKS_PER_SEC 每秒的时钟数变量:typedefsize_t类型定义typedefclock_t类型定义structtm结构体struct... 阅读全文
posted @ 2012-10-11 23:03 Mr.Rico 阅读 (117) | 评论 (0) 编辑
摘要:C语言在 头文件定义了一些宏,当函数参数未知时去获取函数的参数。包括一个va_list类型和三个函数(宏)va_start, va_arg和va_end .变量和定义va_list类型通过stdarg宏定义来访问一个函数的参数表,参数列表的末尾会用省略号省略声明:void va_start(va_l... 阅读全文
posted @ 2012-10-11 23:01 Mr.Rico 阅读 (114) | 评论 (0) 编辑
摘要:在STL中,迭代器主要分为5大类:Input Iterator, Output Iterator, Forward Iterator, Bidirectional Iterator和RandomAccess Iterator。关系如下:其中每一个左边的迭代器都实现了右边迭代器的方法。左边迭代器是对右边迭代器的进一步强化。In this graph, each iterator category implements the functionalities of all categories to its right:(1) Input and output iterators are the 阅读全文
posted @ 2012-10-10 22:13 Mr.Rico 阅读 (401) | 评论 (0) 编辑
摘要:C语言中重要函数的简要分析及实例1. strspn与strcspn2. strtok与strpbrk3. strstr, strchr与strrchr4. 字符串与数值之间的转换:atoi,atol,atof,strtod,strtol,strtoul5. frexp和ldexp1. strspn与strcspn(1)函数strspn:size_t strspn ( const char * str1, const char * str2 );功 能: 在串中查找指定字符集的子集的第一次出现,如果str1中的所有字符都在str2中出现过,那么返回str1的长度。如果第一个字符就不在str2中, 阅读全文
posted @ 2012-08-27 15:42 Mr.Rico 阅读 (179) | 评论 (0) 编辑
摘要:多态性与将实现多态的函数的访问限定符没有任何关系,private 函数仍然可以实现多态,它的指针仍然位于vtbl中,只不过此时该函数的多态一般只能在基类的内部由其他非虚函数调用该函数的时候反映出来(而无法直接在类外部调用该函数来实现多态),访问限定符仅仅限制外部对类的成员的访问权限,它并没有破坏以下规则: 通过基类指针或引用调用成员函数时,如果该函数时非虚的,那么将采用静态绑定,即编译时绑定;如果该函数是虚拟的,则采用动态绑定,即运行时绑定。如下面的例子:#include#includeusingnamespacestd;classBase{private:virtualstringclass 阅读全文
posted @ 2012-08-26 11:13 Mr.Rico 阅读 (383) | 评论 (0) 编辑
摘要:1. C语言中的 sizeof 问题(1)类型转换的问题#include#defineNUM(sizeof(arr)/sizeof(arr[0]))intarr[]={1,2,3,4,5,6,7};intmain(){inti;for(i=-1;iintmain(){inti;i=10;printf("i:%d\n",i);printf("sizeof(i++)is:%d\n",sizeof(i++));printf("i:%d\n",i);return0;}结果是i : 10sizeof(i++) is: 4i : 10为什么第三个 阅读全文
posted @ 2012-08-25 21:13 Mr.Rico 阅读 (265) | 评论 (0) 编辑
摘要:1. 一般说来,volatile用在如下的几个地方:(1)、中断服务程序中修改的供其它程序检测的变量需要加volatile;(2)、多任务环境下各任务间共享的标志应该加volatile;(3)、存储器映射的硬件寄存器通常也要加volatile说明,因为每次对它的读写都可能由不同意义;另外,以上这几种情况经常还要同时考虑数据的完整性(相互关联的几个标志读了一半被打断了重写),在1中可以通过关中断来实现,2中可以禁止任务调度,3中则只能依靠硬件的良好设计了。2. 判断char是有符号还是无符号C语言中的char是有符号还是无符号有时候这个问题和平台或者编译器有关,gcc和 Ms cl 都默认是si 阅读全文
posted @ 2012-08-25 21:07 Mr.Rico 阅读 (169) | 评论 (0) 编辑
摘要:散列Hash函数是一种特殊的映射函数, 散列表Hash Table由散列函数所产生的一种数据结构. 这是一种非常重要的数据结构. 首先, 先了解散列表在数据结构方面的基础: 散列表是用于存储动态集的一种非常有效的数据结构。通过散列函数h(key)的计算结果,直接得到key关键字表示的元素的存储地址。散列技术中,可能会有两个不同的key1和key2,通过h(key)计算得到的地址是一样的,这就发生了冲突。散列技术中散列函数h(key)和解决冲突的技术是最关键的问题。 散列函数要求(1)能快速的计算;(2) 计算结果分布要均匀。 散列函数有如下几种常用的:(1) 除留余数法;(2) 平方取中法;. 阅读全文
posted @ 2012-08-25 20:37 Mr.Rico 阅读 (1002) | 评论 (0) 编辑
摘要:1. C库中的伪随机函数rand的实现 《The GNU C Library》里说的,大概如下: 公式: Y=(a*X+c)mod m 其中,a,c,m都是常数 一种取值是: a = 0x5DEECE66D = 25214903917 c = 0xb = 11 m = 2^48 用上面的公式可以这样写: __int64rand(){static__int64r=0;const__int64a=25214903917;const__int64c=11;const__int64m=1<<48;r=(r*a+c)%m;returnr;}2. ASNI 随机数生成的理解ANSI中和随机数生 阅读全文
posted @ 2012-08-25 20:29 Mr.Rico 阅读 (1522) | 评论 (0) 编辑
摘要:getword函数这儿所说的getword函数,是指从一段字符串中提取出其中的单词。其实这儿主要是分析利用一些标点符号和一些空白字符进行分割而成的单词,还没有达到编译器所使用的对字符串的分析。编译器是根据语言的文法对语言的源代码进行分析。一般需要利用编译原理中的文法分析来得到具体的token。而这儿的比较简单。对于C和C++有不同的实现方式。在C语言中有一个函数,strtok可以帮助实现这个。这个函数主要是根据给定的分隔符来对字符串进行分割。实现代码如下:/**10.C语言中利用strtok对字符串根据特定的字符进行划分*/#include#include#includeintgetwords 阅读全文
posted @ 2012-08-25 12:48 Mr.Rico 阅读 (850) | 评论 (0) 编辑
摘要:有些成员变量的数据类型比较特别,它们的初始化方式也和普通数据类型的成员变量有所不同。这些特殊的类型的成员变量包括: a. 常量型成员变量(const) b. 引用型成员变量 (&) c. 静态成员变量 (static) d. 整型静态常量成员变量 static const int e. 非整型静态常量成员变量 static const double 1. 常量型成员初始化:只能在构造函数的初始化列表中进行直接初始化。 如: classTest{public:constintMY_MASK;Test():MY_MASK(0xff){}};如果不是在初始化列表中对 const 常量进行初始 阅读全文
posted @ 2012-08-25 12:40 Mr.Rico 阅读 (752) | 评论 (0) 编辑
摘要:STL中并没有把heap作为一种容器组件,heap的实现亦需要更低一层的容器组件(诸如list,array,vector)作为其底层机制。Heap是一个类属算法,包含在algorithm头文件中。 在STL中为堆heap的创建和操作提供了4种算法:make_heap,pop_heap,push_heap和sort_heap。1. push_heap: 假定区间[first,last-1)已经包含了一个堆,把区间[first,last)调整为一个堆(从而 把last-1位置上的元素压入堆。 函数原型:voidpush_heap(first,last);voidpush_heap(first,la 阅读全文
posted @ 2012-08-25 08:06 Mr.Rico 阅读 (409) | 评论 (0) 编辑
摘要:这是摘自《More Effective C++ 2007》条款27:要求或禁止在堆中产生对象要求在堆中建立对象 让我们先从必须在堆中建立对象开始说起。为了执行这种限制,你必须找到一种方法禁止以调用"new"以外的其它手段建立对象。这很容易做到。非堆对象(non-heap object)在定义它的地方被自动构造,在生存时间结束时自动被释放,所以只要禁止使用隐式的构造函数和析构函数,就可以实现这种限制。把这些调用变得不合法的一种最直接的方法是把构造函数和析构函数声明为 private。这样做副作用太大。没有理由让这两个函数都是 private。最好让析构函数成为 private 阅读全文
posted @ 2012-08-19 14:21 Mr.Rico 阅读 (446) | 评论 (0) 编辑
摘要:这是摘自《More Effective C++ 2007》 条款24:理解虚函数,多重继承,虚基类和RTTI所需的代价 当调用一个虚拟函数时,被执行的代码必须与调用函数的对象的动态类型相一致;指向对象的指针或引用的类型是不重要的。编译器如何能够高效地提供这种行为呢?大多数编译器是使用 virtual table 和 virtual table pointers。virtual table 和 virtual table pointers 通常被分别地称为 vtbl 和 vptr。 一个 vtbl 通常是一个函数指针数组。(一些编译器使用链表来代替数组,但是基本方法是一样的)在程序中的每个类只要 阅读全文
posted @ 2012-08-19 13:45 Mr.Rico 阅读 (538) | 评论 (0) 编辑
摘要:函数模板与类模板是两大类主要的C++泛型编程的使用方法。类模板可以进行模板偏特化和全特化,而函数模板只能进行全特化。但是类不同的是,函数还有一个重要的特性就是重载,如果将函数模板与函数重载的问题放在一块的时候,问题就变得比较麻烦了。 看下面的一个例子:includeusingnamespacestd;templatevoidf(T){coutvoidf(T*){coutvoidf(int*){cout(int*)"voidf(int*){cout(int*)"(int*)即调用的是第3个函数。这儿容易让人疑惑的是,为什么不是第4个函数:templatevoid f(int* 阅读全文
posted @ 2012-08-17 22:49 Mr.Rico 阅读 (301) | 评论 (0) 编辑
摘要:如果想要删除vector中值为val的元素,最容易想到的方法就是对vector进行遍历,然后遇到值为val时就将其删除。比较好的是vector容器有erase操作。但是这儿需要注意,与list中的erase不同,list的erase操作之后,之前获得的迭代器还是有效的,而在vector中因为vector是顺序存储,所以,一旦删除一个元素,之前获得的迭代器就会失效了,vector.begin()和vector.end()是变化的。注意到,erase的返回值是一个迭代器,而这个迭代器就是指向删除之前元素后的第一个元素。注意到这一点我们可以采用下面的方法实现:voidremove_v(vector& 阅读全文
posted @ 2012-08-17 14:51 Mr.Rico 阅读 (10198) | 评论 (0) 编辑
摘要:在使用C/C++进行编程的过程中,经常会遇到输入输出的问题。 对于C语言中, 1. 格式化输入输出。 在C语言中,最常用的格式化输入输出是scanf和printf函数。 和这两个函数对应的更安全的函数是fscanf和fprintf:指定文件指针 对于字符串的处理还有sscanf和sprintf:指定字符串 声明如下: int printf(const char *format, ...); int fprintf(FILE *stream, const char *format, ...); int sprintf(char *str, const char *format, ...);... 阅读全文
posted @ 2012-08-02 10:18 Mr.Rico 阅读 (21483) | 评论 (1) 编辑
摘要:getline函数是一个比较常见的函数。根据它的名字我们就可以知道这个函数是来完成读入一行数据的。现在对getline函数进行一个总结。在标准C语言中,getline函数是不存在的。下面是一个简单的实现方式:intgetline_(chars[],intlim){intc,i;i=0;while((c=getchar())!=EOF&&c!='\n'&&i0)printf("%s\n",s);return0;}但是这个实现是有问题的,就是遇到空行的时候也会停止的。为了解决这个问题,我们需要重新考虑while循环的判断条件。在上 阅读全文
posted @ 2012-08-01 15:17 Mr.Rico 阅读 (85531) | 评论 (4) 编辑
摘要:这儿所讨论的是x86机器下的内存分配。其他机器下的情况可能不一样。首先,下面是一段测试程序:#includeusingnamespacestd;intmain(){inta[]={1,2,3,4,5,0,-5,-4,-3,-2,-1};char*s="helloworld";char*s2="I'maboy";char*s3="helloworld";floatf=1.0f;doubled=1.0;printf("a:%0#x\n",a);printf("s:%0#x\n",s);pri 阅读全文
posted @ 2012-07-24 21:20 Mr.Rico 阅读 (176) | 评论 (0) 编辑
摘要:之前有文章介绍过临时对象和返回值优化RVO方面的问题。见此处。在C++中,返回对象这一点经常被诟病,因为这个地方的效率比较低,需要进行很多的操作,生成一些临时对象,如果对象比较大的会就会比较耗时。但是在编译器实现的时候,经常是对返回对象的情况进行优化,也就是进行返回值优化 。在g++中,这个是默认已经进行了优化。以前我希望看看到底C++怎么操作的,但是无法看到,就是因为G++进行了默认的返回值优化RVO。今天在晚上发现可以有一中方法来禁止这个RVO,可以参考这儿。具体来说就是在编译的时候,加上-fno-elide-constructors这个选项,即:g++ -o rvo_test rvo_t 阅读全文
posted @ 2012-07-21 11:23 Mr.Rico 阅读 (1660) | 评论 (0) 编辑
摘要:1. 面向对象:封装(数据抽象)是基础,继承是手段,多态是目的;泛型编程:参数化类型(概念抽象)是基础,模板是手段,通用是目的2. 面向对象是运行时问题空间的多态,泛型编程是编译时算法空间的多态3. OO以Type为中心,GP以Concept为中心,而Concept完全独立于Type;OO的type是显式定义的,type之间的关系也是显式定义的,是语言支持的 ;GP的Concept是由算法隐式定义的,Concept之间的关系,是无法用目前的C++语法直接表达的;Concept的Model完全可以是毫无关系的Type,refinement独立于inheritence,original conc. 阅读全文
posted @ 2012-07-16 21:03 Mr.Rico 阅读 (341) | 评论 (0) 编辑
摘要:本篇内容来源于互联网 前言:复杂类型说明要了解指针,多多少少会出现一些比较复杂的类型,所以我先介绍一下如何完全理解一个复杂类型,要理解复杂类型其实很简单,一个类型里会出现很多运算符,他们也像普通的表达式一样,有优先级,其优先级和运算优先级一样,所以我总结了一下其原则:从变量名处起,根据运算符优先级结合,一步一步分析. 下面让我们先从简单的类型开始慢慢分析吧:intp;//这是一个普通的整型变量int*p;//首先从P处开始,先与*结合,所以说明P是一个指针,然后再与int结合,说明指针所指向的内容的类型为int型.所以P是一个返回整型数据的指针intp[3];//首先从P处开始,先与[]结合. 阅读全文
posted @ 2012-07-16 15:33 Mr.Rico 阅读 (174) | 评论 (0) 编辑
摘要:参考:http://blog.csdn.net/haoel/article/details/3081328,http://blog.csdn.net/haoel/article/details/3081385前言 07年12月,我写了一篇《C++虚函数表解析》 的文章,引起了大家的兴趣。有很多朋友对我的文章留了言,有鼓励我的,有批评我的,还有很多问问题的。我在这里一并对大家的留言表示感谢。这也是我为什么 再写一篇续言的原因。因为,在上一篇文章中,我用了的示例都是非常简单的,主要是为了说明一些机理上的问题,也是为了图一些表达上方便和简单。不想,这篇 文章成为了打开C++对象模型内存布局的一个引子 阅读全文
posted @ 2012-07-15 19:25 Mr.Rico 阅读 (114) | 评论 (0) 编辑
摘要:参考:http://www.cnblogs.com/itech/archive/2009/02/27/1399996.html一 虚继承1) 代码:#includeusingnamespacestd;classB{public:inti;virtualvoidvB(){cout(pB);pGD->i=10;pGD->x=20;pGD->y=30;pGD->a=40;PrintMemberAndVT(pGD);deletepGD;}6)验证代码结果:7)总结:虚继承,使公共的基类在子类中只有一份,我们看到虚继承在多重继承的基础上多了vbtable来存储到公共基类的偏移。二 阅读全文
posted @ 2012-07-15 18:19 Mr.Rico 阅读 (211) | 评论 (0) 编辑
摘要:之前有对虚函数机制的讲解,见这先讨论是多级继承的虚函数表。首先是没有函数覆盖的情况,继承方式如下图所示:对于实例DDerive dd;其所对应的虚函数列表是:测试代码如下:View Code classBase{public:typedefvoid(Base::*Fun)();virtualvoidf(){Funq=&Base::f;cout<<"Base::f->"<<(int)*(void**)&q<<endl;}virtualvoidg(){Funq=&Base::g;cout<<" 阅读全文
posted @ 2012-07-15 17:24 Mr.Rico 阅读 (454) | 评论 (0) 编辑
摘要:C++中的虚函数机制 虚函数的定义:虚函数必须是类的非静态成员函数(且非构造函数),其访问权限是 public(可以定义为 private or proteceted, 但是对于多态来说,没有意义)。在基类的类定义中定义虚函数的一般形式:virtual 函数返回值类型 虚函数名(形参表){ 函数体 }虚函数的作用是实现动态联编,也就是在程序的运行阶段动态地选择合适的成员函数,在定义了虚函数后,可以在基类的派生类中对虚函数重新定义(形式也是:virtual 函数返回值类型 虚函数名(形参表){ 函数体 }),在派生类中重新定义的函数应与虚函数具有相同的形参个数和形参类型。以实现统一的接口,不同定 阅读全文
posted @ 2012-07-15 14:06 Mr.Rico 阅读 (1424) | 评论 (0) 编辑
摘要:内存对齐常量折叠 堆栈解退(stack unwinding) 模板特化模板偏特化 模板实例化 函数对象 单一定义规则(One-Definition Rule,ODR) 自引用 对象切片(object slicing)/切割:当把一个派生类对象赋给一个基类对象时,会发生对象切割。(另外用基类对象强制转换派生类对象也会),多态的实现是通过指针和引用;而对象的转换只会造成对象切割,不能实现多态。 所有权语义(owership semantics) 破坏性复制语义(distructive copy semantics) 菱形继承 向下强制:基类到派生类的转换 向上强制:派生类到基类的转换 交叉强制:从 阅读全文
posted @ 2012-07-02 22:10 Mr.Rico 阅读 (2080) | 评论 (0) 编辑
摘要:常量 起初读者可能认为合乎逻辑的选择是把一个const放在类里,但这不会产生预期的结果。在一个类里,const 恢复它在C中的一部分意思。 它在每个类对象里分配存储并代表一个值,这个值一旦被初始化以后就不能改变。在一个类里使用const的意思是“在这个对象声明期内,这个是一个常量”。 然而,对这个常量来讲,每个不同的对象可以含一个不同的值。 把一个内部数据类型封装在一个类里以保证用构造函数初始化,是很用的。例如 class interger{int i;public:interger(int ... 阅读全文
posted @ 2012-07-02 02:41 Mr.Rico 阅读 (654) | 评论 (0) 编辑
摘要:1. 初始化一个引用变量必须在定义的时候。 而所有的运算符操作都被视为赋值而不是初始化,所以引用参数的初始化必须在初始化列表中进行。 class Test{ public: Test(int val) : ref_(val){} ~Test() {} private: int & ... 阅读全文
posted @ 2012-07-02 02:36 Mr.Rico 阅读 (465) | 评论 (0) 编辑
摘要:1、什么是static? static是C++中很常用的修饰符,它被用来控制变量的存储方式和可见性。 2、为什么要引入static? 函数内部定义的变量,在程序执行到它的定义处时,编译器为它在栈上分配空间,大家知道,函数在栈上分配的空间在此函数执行结束时会释放掉,这样就产生了一个问题: 如果想将函数中此变量的值保存至下一次调用时,如何实现? 最容易想到的方法是定义一个全局的变量,但定义为一个全局变量有许多缺点,最明显的缺点是破坏了此变量的访问范围(使得在此函数中定义的变量,不仅仅受此函数控制)。 3、什么时候用static? 需要 一个... 阅读全文
posted @ 2012-07-02 02:33 Mr.Rico 阅读 (650) | 评论 (0) 编辑
摘要:这是C++中所支持的两种初始化方式。复制初始化使用=符号,而直接初始化将初始化式放在圆括号中。(1)对于一般的内建类型,这两种初始化基本上没有区别。int a(5);//直接初始化int a=5;//复制初始化int a=int (5);//直接初始化(2)当用于类类型对象时,初始化的复制形式和直接形式有所不同:直接初始化直接调用与实参匹配的构造函数,复制初始化总是调用复制构造函数。复制初始化首先使用指定构造函数创建一个临时对象,然后使用复制构造函数将那个临时对象复制到正在创建的对象。string null_book = "9-999-99999-9 ";//copy-in 阅读全文
posted @ 2012-06-25 22:05 Mr.Rico 阅读 (2918) | 评论 (0) 编辑
摘要:栈增长和大端/小端问题是和CPU相关的两个问题。在内存管理中,与栈对应是堆。对于堆来讲,生长方向是向上的,也就是向着内存地址增加的方向;对于栈来讲,它的生长方式是向下的,是向着内存地址减小的方向增长。在内存中,“堆”和“栈”共用全部的自由空间,只不过各自的起始地址和增长方向不同,它们之间并没有一个固定的界限,如果在运行时,“堆”和 “栈”增长到发生了相互覆盖时,称为“栈堆冲突”,系统肯定垮台。在常见的x86中内存中栈的增长方向就是从高地址向低地址增长。我们可以通过一些代码来判断栈的增长方向:#include<stdio.h>staticintstack_dir;staticvoid 阅读全文
posted @ 2012-06-22 20:47 Mr.Rico 阅读 (11840) | 评论 (2) 编辑
摘要:今天在网上看到这个问题,自以为的输出是3.0,但是实际去跑一下,可以发现结果是0.0000这一句虽然不长,但是其中蕴涵的知识点是很多的。第一,10/3的结果是什么?这个很显然结果应该是3第二,printf语句格式化输出的使用%f就是要输出浮点数,但是我们也发现给的参数其实是个整型数。所以也就出现了上面的结果。第三,printf的原理是什么?这儿就牵扯到C中的不定参数的使用方法。具体可见这儿 简单来说就是,printf从栈中取参数的时候是根据格式化语句中要求进行取数的。这儿是%f,而浮点数是4个字节(32位操作系统),所以,要从栈中取4个字节,并且是按“浮点数的方式”。正好,参数3是个整型数,. 阅读全文
posted @ 2012-05-18 20:08 Mr.Rico 阅读 (1713) | 评论 (1) 编辑
摘要:为栈实现高效的max操作 题目: 请设计一个栈,除了提供push(压栈),pop(出栈),peak(取栈顶元素)操作以外,还能提供max(取栈中最大值)的功能,并使得时间复杂度最小。注:请仔细思考后再看下面的答案1. 方案一(不可行)设计一个成员max,等于栈中最大的元素,在每次push操作后,新压入的元素与max比较,然后将max赋值为它们中的大的元素值。这样,max函数则返回max。问题:如果栈中等于max的元素pop出去后,该max就不是栈中的最大值了。2. 方案二(可行,效率太低)在【方案一】的基础上改进,每当栈中等于max的元素pop出去后,则把剩余元素依次pop到临时数组,找出最大 阅读全文
posted @ 2012-05-16 22:51 Mr.Rico 阅读 (298) | 评论 (0) 编辑
摘要:交换两个整型数是C/C++中最常见的操作。实现这个操作的方法很多。最基本的方法就是使用一个临时变量,具体的代码如下:inta,b;inttmp;tmp=a;a=b;b=tmp;如果以函数的形式写出来的话就是:voidswap(int*a,int*b){inttmp;tmp=*a;*a=*b;*b=tmp;}在C++中,可以使用引用来实现的比较优雅:voidswap(int&a,int&b){inttmp;tmp=a;a=b;b=tmp;}另外,还经常出现的一种情况是不使用临时变量来交换两个整型数,一般常见的方法有两种:加法和异或运算,具体如下表所示: ... 阅读全文
posted @ 2012-05-16 20:38 Mr.Rico 阅读 (12605) | 评论 (2) 编辑
摘要:C语言提供类似于矩阵的多维数组,在一些进行数学运算的程序中会经常用到。从形式 上看多维数组是由多个一维数组组成的,但C语言处理多维数组的方法和一维数组一样,都是线性存储,连续分配存储空间,可以用带偏移量(offset)的一 维数组来访问多维数组。而在数组规模不确定的情况下,就需要用malloc函数动态分配存储空间。这里的数组规模不确定指的是数组的维数确定,而每一维的 元素个数是不确定的。例如根据用户输入的行数和列数来确定一个二维数组。下面使用两种方式来进行二维数组分配:对应的代码如下: #include<stdio.h>#include<stdlib.h>#define 阅读全文
posted @ 2012-05-14 11:01 Mr.Rico 阅读 (556) | 评论 (0) 编辑
摘要:c++类的构造函数详解 一、 构造函数是干什么的 class Counter { public: // 类Counter的构造函数 // 特点:以类名作为函数名,无返回类型 Counter() { m_value = 0; } private: // 数据成员 int m_value; } 该类对象被创建时,编译系统对象分配内存空间,并自动调用该构造函数->由构造函数完成成员的初始化工作 eg:Counter c1; 编译系统为对象c1的每个数据成员(m_value)分配内存空间,并调用构造函数Counter( )自动地初始化对象c1的m_value... 阅读全文
posted @ 2012-05-11 17:50 Mr.Rico 阅读 (79438) | 评论 (11) 编辑
摘要:使用Memoization,以避免递归重复计算考虑Fibonacci(斐波那契)问题;Fibonacci问题是可以通过简单的递归方法来解决:intfib(n){if(n==0||n==1){return1;}else{returnfib(n-2)+fib(n-1);}}注:在这里,我们考虑Fibonacci 系列从1开始,因此,该系列看起来:1,1,2,3,5,8,... 注意:从递归树,我们计算fib(3)函数2次,fib(2)函数3次。这是相同函数的重复计算。如果n非常大,fib这个简单的技术叫做Memoization,可以被用在递归,加强计算速度。fibonacci 函数Memoizat 阅读全文
posted @ 2012-05-08 10:39 Mr.Rico 阅读 (3937) | 评论 (0) 编辑
摘要:原文:http://www.linuxforu.com/2011/12/loading-library-files-in-cpp/?utm_source=feedburner&utm_medium=feed&utm_campaign=Feed%3A+LinuxForYou+%28LINUXForYou+%29在C语言中载入库比较容易,而在C++中则比较麻烦。在C语言中函数都唯一的,这样在库中可以直接使用函数名作为函数的记号,而在C++中由于函数重载和多态的存在,使得C++中函数名不能直接作为函数的记号。为了解决这个问题,C++中使用是Name mangling技术,对不同的函数 阅读全文
posted @ 2012-04-26 17:34 Mr.Rico 阅读 (1147) | 评论 (0) 编辑
摘要:C代码优化方案1. 使用尽量小的数据类型 2. 求余运算使用位操作来代替求余运算:只要是2^n的取模,都可以使用位操作来代替。 使用移位运算来代替乘法运算。比如: 3. 避免不必要的整数除法整数除法是整数运算中最慢的,所以应该尽可能避免。一种可能减少整数除法的地方是连除,这里除法可以由乘法替代,但是存在副作用就是,乘法有可能溢出。4. 使用符合操作表达式,都能获得高质量的程序代码。5. 结构体成员布局我们都知道对于结构体存在内存对其的问题,所以为了付出最小代价情况下得到结构体的内存对齐,可以采取下面的一些策略:按数据类型的长度排序,先存放多字节数据,然后再存放单字节数据,这样可以避免内存空洞。 阅读全文
posted @ 2012-04-11 21:41 Mr.Rico 阅读 (279) | 评论 (0) 编辑
摘要:这个是在《C/C++程序员实用大全·精华版:C/C++最佳编程指南》一书中提到了"ANSI设备驱动器"。在shell编程中也是类似的。要是通过彩色化提示符来增加个性化,就要用到转义序列。 转义序列就是一个让 shell 执行一个特殊步骤的控制指令。 转义序列通常都是以 ESC 开头(这也是它的命名原因)。 在 shell 里表示为 ^[。这种表示法需要一点时间去适应, 也可以用 \033 完成相同的工作(ESC 的 ASCII 码用十进制表示就是 27, = 用八进制表示的 33)。要直接在 shell 里面输入转义序列我们需要先按 ctrl-v:CTRL-v E 阅读全文
posted @ 2012-03-27 21:11 Mr.Rico 阅读 (435) | 评论 (0) 编辑
摘要:这是在《C专家编程》一书上提到的一个问题。我在网上搜索了一下,找到了一些解法,总结如下。首先是《C专家编程》上提到解法:#define ISUNSIGNED(a) (a>=0 && ~a>=0)#define ISUNSIGNED(type) ((type)0-1 > 0)第二个从类型来判断,没有问题。而第一个只能用在K&R C里,在ANSI C里就不行了。当这个宏被用在int/unsigned int时,没有任何问题。但是当使用在char和short上就会出错。分析: 此宏在int/unsigned int好使的原因是宏中的a的精度始终不会发生变化, 阅读全文
posted @ 2012-03-27 21:10 Mr.Rico 阅读 (2522) | 评论 (1) 编辑
摘要:内联函数并不总是内联 Inline function是在C++中引入的一种机制,它可以拓展函数代码,避免调用函数的额外开销。在Linux环境下,gcc编译选项必须加上优化选项才能使inline有效。inline与static的关系在这儿有一个比较详细的分析:http://www.cnblogs.com/xkfz007/articles/2370640.html 内联函数(inline)机制与陷阱 内联机制被引入C++作为对宏(Macro)机制的改进和补充(不是取代)。内联函数的参数传递机制与普通函数相同。但是编译器会在每处调用内联函数的地方将内联函数的内容展开。这样既避免了函数调用的开销... 阅读全文
posted @ 2012-03-27 21:09 Mr.Rico 阅读 (14128) | 评论 (0) 编辑
摘要:const: const 是一个左结合的类型修饰符,它与其左侧的类型修饰符和为一个类型修饰符。const可以用于定义常量,可以限定函数的引用参数(因为传值的参数根本不用限定),可以限定函数返回值为引用的情况。还有一个用法是修饰类的成员函数。这样情况下,在类内的声明和类外的定义都要加上const。 还有一种情况是,声明类的const成员变量的时候,如何进行初始化。在这种情况下,由于常量不能修改,所以只能在构造函数的初始化列表中进行复制初始化。如果同时声明为了static时可以在类外进行初始化,但此时不能加static关键字。mutable: mutalbe的中文意思是"可变的,易变的& 阅读全文
posted @ 2012-03-27 21:09 Mr.Rico 阅读 (1994) | 评论 (0) 编辑
摘要:在看《你必须知道的496个C语言问题》一书中,提到"达夫设备"这个东西,主要是下面的代码: register n = (count + 7) / 8; /\* count > 0 assumed \*/ switch (count % 8) { case 0: do { \*to = \*from++; case 7: \*to = \*from++; case 6: \*to = \*from++; case 5: \*to = \*from++; case 4: \*to = \*from++; ... 阅读全文
posted @ 2012-03-27 21:08 Mr.Rico 阅读 (4787) | 评论 (3) 编辑
摘要:下面是一些比较重要的宏定义,记录一下:assert断言:#define assert(cond) ((cond)?(void)0:_assert(#cond,__FILE__,__LINE__)) void _assert(char*cond,char*filename,long lineno) { printf("assert:%s in file:%s, at line:%d\n",cond,filename,lineno); }获得结构体中域的偏移量#define offsetof(type,field) ((int)((char*)&(((type*)0)- 阅读全文
posted @ 2012-03-27 21:07 Mr.Rico 阅读 (500) | 评论 (0) 编辑
摘要:Quine 以哲学家 Willard van Orman Quine (1908-2000) 而命名,表示一个可以生成他自己的完全的源代码的程序。编写出某个语言中最简短的 quine 通常作为黑客们的消遣。作为真正的 quine ,有一些约定:程序不能接受输入或者是打开文件,因为那样就可以直接输入源代码或者是把源代码文件直接打开再重新打印出来,就没有什么意思了;同时,一个完全空白的程序(产生完全空白的输出,即没有输出)也并不能称作 quine 。quine 的想法最初出现在 Bratley, Paul and Jean Millo. "Computer Recreations; Se 阅读全文
posted @ 2012-03-27 21:07 Mr.Rico 阅读 (5942) | 评论 (0) 编辑
摘要:网上搜索了一下,发现检测内存泄漏的工具还是很多的。下面是从网上找到的一些材料,主要是在linux系统中内存泄漏的检测方法。(1)什么是内存内存泄漏? 在此,谈论的是程序设计中内存泄漏和错误的问题,不过,并不是所有的程序都有这一问题。首先,泄漏等一些内存方面的问题在有的程序语言中是不容易发生的。这些程序语言一般都认为内存管理太重要了,所以不能由程序员来处理,最好还是由程序语言设计者来处理这些问题,这样的语言有Perl、Java等等。 然而,在一些语言(最典型的就是C和C++)中,程序语言的设计者也认为内存管理太重要,但必需由开发人员自己来处理。内存泄漏指的是程序员动态分配了内存,但是在... 阅读全文
posted @ 2012-03-27 21:05 Mr.Rico 阅读 (875) | 评论 (0) 编辑
摘要:先通过一个小程序来看一看: #include void foo(int x, int y, int z) { printf("x = %d at [%X]n", x, &x); printf("y = %d at [%X]n", y, &y); printf("z = %d at [%X]n", z, &z); } int main(int argc, char *argv[]) { foo(100, 200, 300); return 0; }运行结果:x = 100 at [... 阅读全文
posted @ 2012-03-27 21:04 Mr.Rico 阅读 (23100) | 评论 (1) 编辑
摘要:线性同余随机数生成器介绍:古老的LCG(linearcongruentialgenerator)代表了最好最朴素的伪随机数产生器算法。主要原因是容易理解,容易实现,而且速度快。LCG 算法数学上基于公式:X(n+1)=(a*X(n)+c)%m其中,各系数为:模m,m>0系数a,0<a<m增量c,0<=c<m原始值(种子)0<=X(0)<m其中参数c,m,a比较敏感,或者说直接影响了伪随机数产生的质量。一般而言,高LCG的m是2的指数次幂(一般2^32或者2^64),因为这样取模操作截断最右的32或64位就可以了。多数编译器的库中使用了该理论实现其伪随机 阅读全文
posted @ 2012-03-27 21:03 Mr.Rico 阅读 (19896) | 评论 (0) 编辑
摘要:编译器的发展:上世纪50年代,IBM的John Backus带领一个研究小组对FORTRAN语言及其编译器进行开发。但由于当时人们对编译理论了解不多,开发工作变得既复杂又艰苦。与此同时,Noam Chomsky开始了他对自然语言结构的研究。他的发现最终使得编译器的结构异常简单,甚至还带有了一些自动化。Chomsky的研究导致了根据语言文法的难易程度以及识别它们所需要的算法来对语言分类。正如现在所称的Chomsky架构(Chomsky Hierarchy),它包括了文法的四个层次:0型文法、1型文法、2型文法和3型文法,且其中的每一个都是其前者的特殊情况。2型文法(或上下文无关文法)被证明是程序 阅读全文
posted @ 2012-03-27 21:01 Mr.Rico 阅读 (2539) | 评论 (0) 编辑
摘要:1. 关键字volatile有什么含意?并给出三个不同的例子。 一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。下面是volatile变量的几个例子:(1)并行设备的硬件寄存器(如:状态寄存器) (2)一个中断服务子程序中会访问到的非自动变量(Non-automatic variables) (3) 多线程应用中被几个任务共享的变量 回答不出这个问题的人是不会被雇佣的。我认为这是区分C程序员和嵌入式系统程序员的最基本的问题。搞嵌入式 阅读全文
posted @ 2012-03-27 20:54 Mr.Rico 阅读 (717) | 评论 (0) 编辑
摘要:这是一篇从网上看到的一篇文章,讲得挺有道理。记录下来。(1) 精英化趋势 C++是一门引起无数争议的语言。眼下最常听到的声音则是C++将趋于没落,会被某某语言取代。我很怀疑这种论调的起点是商业宣传,C++的真实趋势应该是越来越倾向于精英化。精英化是指在可用可不用C++的领域中,C++将逐渐退出,而所有剩下必须用C++的领域通常都是附加值比较高,难度较高的领域,比如:操作系统,数据库,大型网站后端等。这一过程造成的现象就是在TIOBE上,C++的份额逐步下降。但就像经济上挤泡沫一样,这倒不是C++衰落了,而是原本人们对C++的期望过高了。早在1995年,美国的调查机构就曾经预测:"终端 阅读全文
posted @ 2012-03-27 20:45 Mr.Rico 阅读 (1122) | 评论 (0) 编辑
摘要:C和C++之间的关系非常的密切,我们也都知道C++是从C扩充而来的,但是这并不表示C++对C完全兼容。C++并不是C的超集,C的有些特性在C++中并不适用。看完《C专家编程》之后,从中了解到了几个。简单总结一下。 (1)在C++中,用户代码不能调用main函数,但在C语言中却是允许的。(所以可以递归调用main函数)比如:#include <stdio.h>int a=5;int main(){if(a==0)return 0;else{printf("call main again:%d\n",a);a--;main();}return 0;}输出如下:cal 阅读全文
posted @ 2012-03-12 15:33 Mr.Rico 阅读 (731) | 评论 (0) 编辑
摘要:对于下面的程序:View Code #include<iostream>#include<string>usingstd::string;//usingstd::size_t;usingstd::endl;usingstd::cout;classItem_base{public:Item_base(conststring&book="",doublesales_price=0.0):isbn(book),price(sales_price){cout<<"base:constructor"<<end 阅读全文
posted @ 2012-03-05 11:34 Mr.Rico 阅读 (214) | 评论 (0) 编辑
摘要:1. const 在C和C++中的区别 C++中的const正常情况下是看成编译期的常量,编译器并不为const分配空间,只是在编译的时候将期值保存在名字表中,并在适当的时候折合在代码中. 所以在C++中const修饰的量可以用在数组的定义中。 而在C中,const是一个不能被改变的普通变量,既然是变量,就要占用存储空间,所以编译器不知道编译时的值.而且,数组定义时的下标必须为常量. 在C语言中: const int size; 这个语句是正确的,因为它被C编译器看作一个声明,指明在别的地方分配存储空间.但在C++中这样写是不正确的.C++中const默认是内... 阅读全文
posted @ 2012-02-27 21:56 Mr.Rico 阅读 (11136) | 评论 (0) 编辑
摘要:2011年4月9日10:09:19c语言中的浮点数在内存中的表示(VC++编译器中):char:1个字节short:2个字节int:4字节long:4字节float:4字节(单精度)double:8字节(双精度) 参考:http://www.cnblogs.com/jillzhang/archive/2007/06/24/793901.html 无论是单精度还是双精度在存储中都分为三个部分: 符号位(Sign) : 0代表正,1代表为负 指数位(Exponent):用于存储科学计数法中的指数数据,并且采用移位存储 尾数部分(Mantissa):尾数部分 其中float的存储... 阅读全文
posted @ 2012-02-27 20:39 Mr.Rico 阅读 (15265) | 评论 (8) 编辑
摘要:2011年4月9日17:42:57C中的字符串数组与字符串指针的区别 从上面的截图,我们可以看到字符数组和字符串的差别。他们的类型是不同的,比如上面的代码中,filename的类型是char[12],而pname的类型是char*,&filename的结果是数组指针,图中显示的是char[12]*。还可以发现,对于pname和p虽然是两个不同的指针,但是他们都指向同一个地址,这也是编译器投机取巧的地方,因为他们都是指向"fangzhen"这个字符串,所以编译器就只存储一次。还有&"fangzhen"的用法也是可以的。2011年4月10日1 阅读全文
posted @ 2012-02-27 20:06 Mr.Rico 阅读 (3407) | 评论 (2) 编辑
摘要:可以使用fwrite()将一个结构体写入文件: fwrite(&some_struct,sizeof somestruct,1,fp);对应的fread函数可以再把它读出来,此处fwrite受到一个结构的指针并把这个结构的内存映像作为字节流写入文件。sizeof操作符计算出结构占用的字节数。但是这样用内存映像写出的数据文件却是不能够移植的,尤其是当结构中包含浮点成员或指针的时候。结构的内存布局跟机器和编译器都有关。不同的编译器可能使用不同数量的填充位,不同机器上基本类型的大小和字节顺序也不尽相同。因此,作为内存映像写出的结构在别的机器上(甚至是被别的编译器编译之后)不一定能被读回来。 阅读全文
posted @ 2012-02-17 16:42 Mr.Rico 阅读 (13515) | 评论 (0) 编辑
摘要:/Files/xkfz/为什么采用虚函数virtual.ppt C++中的继承与虚函数各种概念 虚继承与一般继承 虚继承和一般的继承不同,一般的继承,在目前大多数的C++编译器实现的对象模型中,派生类对象会直接包含基类对象的字段。而虚继承的情况,派生类对象不会直接包含基类对象的字段,而是通过一个间接的指针去存取基类对象中的字段。 继承的特性 继承是面向对象中引入的重要特性之一,它的一个重要的特点就是子类是父类,父类不是子类。也就是说: 1. 如果基类指针指向子类对象(pbase=&pchild),则该指针只能调用基类定义了的函数;(因为这个地方是静态绑定,而静态绑定所依赖的就是指... 阅读全文
posted @ 2012-02-16 16:01 Mr.Rico 阅读 (4333) | 评论 (0) 编辑
摘要:在C和C++中是不同的,我们知道C语言比较宽松、灵活,而C++的目标就是改变C语言比较宽松的特点,实行了比较严格的做法,包括严格的类型检查等等。实际上,在C语言中,main函数可被递归调用,而在C++标准中,main函数不可以被递归调用。C中递归调用: (参考:http://blog.csdn.net/songkexin/article/details/1842654#reply)#include<stdio.h>intmain(){intc;if((c=getchar())!=EOF)//EOF用Ctrl+Z(win)//Ctrl+D(linux){main();}printf( 阅读全文
posted @ 2012-02-16 10:55 Mr.Rico 阅读 (4022) | 评论 (1) 编辑
摘要:参考:http://blog.csdn.net/wanwenweifly4/article/details/6739687 红色是我添加的,其他地方是原作者的。 主要是看了上面的这篇“从底层汇编理解 c++ 引用实现机制“的文章之后,觉得不错。就转了过来,同时,对文中的程序都在自己的机器上验证了一下。 使用的G++版本:g++ (GCC) 4.5.1 20100924 如果要查看汇编后代码与源码的关系,我用的方法是: 先用g++生成带有调试信息的目标文件:g++ -g -c ref.cc 然后再利用objdump命令查看目标文件ref.o:objdump -S ref... 阅读全文
posted @ 2012-02-05 09:25 Mr.Rico 阅读 (1359) | 评论 (1) 编辑
摘要:开始学习在Linux下写程序,利用gcc进行编译的时候经常需要添加一些选项,为了便于查找,将这写常用的选项整理出来。GCC常用选项 -c 通知GCC取消链接步骤,即编译源码并在最后生成目标文件; -Dmacro 定义指定的宏,使它能够通过源码中的#ifdef进行检验; -E 不经过编译预处理程序的输出而输送至标准输出; -g3 获得有关调试程序的详细信息,它不能与-o选项联合使用; -Idirectory 在包含文件搜索路径的起点处添加指定目录; -llibrary 提示链接程序在创建最终可执行文件时包含指定的库; -O、-O2、-O3 将优化状态打开,该选项不能与-g选项联合使用; -S 要 阅读全文
posted @ 2012-02-02 22:13 Mr.Rico 阅读 (146) | 评论 (0) 编辑
摘要:内存对齐是编译器为了便于CPU快速访问而采用的一项技术,对于不同的编译器有不同的处理方法。Win32平台下的微软VC编译器在默认情况下采用如下的对齐规则:任何基本数据类型T的对齐模数就是T的大小,即sizeof(T)。比如对于double类型(8字节),就要求该类型数据的地址总是8的倍数,而char类型数据(1字节)则可以从任何一个地址开始。Linux下的GCC奉行的是另外一套规则:任何2字节大小(包括单字节吗?)的数据类型(比如short)的对齐模数是2,而其它所有超过2字节的数据类型(比如long,double)都以4为对齐模数。下面的程序可以验证:#include<stdio.h& 阅读全文
posted @ 2011-12-21 23:37 Mr.Rico 阅读 (1816) | 评论 (2) 编辑
摘要:最近在跑一些程序,需要计算程序运行的时间,然后搜索了一下相关的材料,发现下面的一个比较好的方法,可以实现毫秒级的计时: #include<sys/timeb.h>#ifdefined(WIN32)#defineTIMEB_timeb#defineftime_ftime#else#defineTIMEBtimeb#endiftime_tltime1,ltime2,tmp_time;structTIMEBtstruct1,tstruct2;ftime(&tstruct1);//starttimemstime(&ltime1);//starttimes//worktime 阅读全文
posted @ 2011-11-14 14:47 Mr.Rico 阅读 (17652) | 评论 (0) 编辑
摘要:昨天在linux下运行一个C程序,是处理一段视频中的每一帧的,本来在程序中是要每处理完一帧就要输出一条信息的,但是在运行是却不显示,而是在程序运行完成之后一块输出的,但是在windows中运行程序就没有这个问题。如果是这样的话,就非常不爽了,因为本来是想通过程序的输出来得到程序当前的运行状况,现在却达不到这种效果。然后上网上搜索了一下,看来果然有解决方案。存在这个问题的主要原因就是在调用printf输出信息后,程序并不是立即输出,而是将其输出到了缓存中,所以,我们要做的就是在printf之后立即将缓存中的信息输出到终端。所以可以在printf之后添加fflush(stdout),这样就能立即将 阅读全文
posted @ 2011-10-24 10:45 Mr.Rico 阅读 (3357) | 评论 (0) 编辑