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

GNU Readline 库及编程简介
摘要:用过 Bash 命令行的一定知道,Bash 有几个特性:TAB键可以用来命令补全↑或↓键可以用来快速输入历史命令还有一些交互式行编辑快捷键:C-A/C-E将光标移到行首/行尾C-B/C-F将光标向左/向右移动一个位置C-D删除光标下的一个字符C-K删除光标及光标到行尾的所有字符C-U删除光标到行首的... 阅读全文

posted @ 2014-12-09 22:29 hazir 阅读(25349) 评论(2) 推荐(4) 编辑

为什么 C++ 中成员函数指针是 16 字节?
摘要:当我们讨论指针时,通常假设它是一种可以用void *指针来表示的东西,在 x86_64 平台下是 8 个字节大小。例如,下面是来自维基百科中关于 x86_64 的文章的摘录:Pushes and pops on the stack are always in 8-byte strides, andp... 阅读全文

posted @ 2014-12-02 22:26 hazir 阅读(5129) 评论(0) 推荐(5) 编辑

C 语言中 setjmp 和 longjmp
摘要:在 C 语言中,我们不能使用goto语句来跳转到另一个函数中的某个label处;但提供了两个函数——setjmp和longjmp来完成这种类型的分支跳转。后面我们会看到这两个函数在处理异常上面的非常有用。setjmp 和 longjmp 使用方法我们都知道要想在一个函数内进行跳转,可以使用goto语句(不知怎么该语句在中国学生眼中就是臭名昭著,几乎所有国内教材都一刀切地教大家尽量不要使用它,但在我看来,这根本不是语言的问题,而是使用该语言的人,看看 Linux 内核中遍地是 goto 语句的应用吧!),但如果从一个函数内跳转到另一个函数的某处,goto 是不能完成的,那该如何实现呢?函数间跳转 阅读全文

posted @ 2013-11-03 15:54 hazir 阅读(33016) 评论(10) 推荐(19) 编辑

GCC 中零长数组与变长数组
摘要:前两天看程序,发现在某个函数中有下面这段程序:int n; //define a variable nint array[n]; //define an array with length n在我所学的C语言知识中,这种数组的定义在编译时就应该有问题的,因为定义数组时,数组的长度必须要是一个大于0的整型字面值或定义为 const 的常量。例如下面这样int array1[10]; //validint const N = 10;int array2[N]; //validint n = 10;int array3[n]; //i... 阅读全文

posted @ 2013-10-27 10:18 hazir 阅读(13838) 评论(11) 推荐(5) 编辑

Linux Kernel代码艺术——数组初始化
摘要:前几天看内核中系统调用代码,在系统调用向量表初始化中,有下面这段代码写的让我有点摸不着头脑:const sys_call_ptr_t sys_call_table[__NR_syscall_max+1] = { /* * Smells like a compiler bug -- it doesn't work * when the & below is removed. */ [0 ... __NR_syscall_max] = &sys_ni_syscall,#include };咱先不管上面代码的意思,先来回顾一下 C 语言中数组初始化的相关知识,然后... 阅读全文

posted @ 2013-09-26 18:57 hazir 阅读(4176) 评论(10) 推荐(6) 编辑

C语言中结构体赋值问题的讨论
摘要:今天帮师姐调一个程序的BUG,师姐的程序中有个结构体直接赋值的语句,在我印象中结构体好像是不能直接赋值的,正如数组不能直接赋值那样,我怀疑这个地方有问题,但最后证明并不是这个问题。那么就总结一下C语言中结构体赋值的问题吧:结构体直接赋值的实现下面是一个实例:#include struct Foo { char a; int b; double c;}foo1, foo2; //define two structs with three different fieldsvoid struct_assign(void){ foo2 = foo1; ... 阅读全文

posted @ 2013-07-23 22:08 hazir 阅读(34012) 评论(6) 推荐(3) 编辑

Linux Kernel 代码艺术——编译时断言
摘要:本系列文章主要写我在阅读Linux内核过程中,关注的比较难以理解但又设计巧妙的代码片段(不关注OS的各个模块的设计思想,此部分我准备写在“深入理解Linux Kernel” 系列文章中),一来通过内核代码复习一下C语言及汇编语言的语法,二来学习内核开发大牛们书写代码的风格及思路。在内核文件 include/linux/bug.h中,有下面两行的宏定义:1 2 3 4 5 6 /* Force a compilation... 阅读全文

posted @ 2013-07-15 21:08 hazir 阅读(3700) 评论(1) 推荐(2) 编辑

五个好的C语言编程实践
摘要:前几天,我看到一个关于编程语言的调查,我发现到目前为止,C 编程语言在全球开发者中仍然稳居前三。如此多的代码使用C来编写,我想分享我多年学习总结的一些好的C语言编程实践。不要使用gets()和strcpy()再也不要使用诸如gets()、strcpy()、sprintf()等等这些函数,这已经是一个广为人知的一个事实,但这些函数仍然在库中,以用来支持那些已经使用这些函数的代码。如果你使用man手册关于gets()的说明,会发现:Never use gets(). Because it is impossible to tell without knowing the data in advan 阅读全文

posted @ 2013-05-22 19:04 hazir 阅读(1173) 评论(1) 推荐(2) 编辑

从IEEE754标准谈C语言浮点数据类型
摘要:先看下面几个问题,如果你能准确地回答,那么此篇文章将不适合你:计算机中怎样表示浮点数的,与整型的表示方法有什么不同?32位精度的float类型和64位精度的double类型能表示浮点数最大范围是多少?该C语言语句 printf("%d\n", 2.5); 输出结果是什么,为什么?我先说在此之前我如果回答,答案如下:计算机中有符号整型采用补码进行表示,浮点型怎么表示没想过。float类型可以表示-232-1~232,double类型可以表示-264-1~264。输出格式要求输出整型,而数是浮点型,类型转化之后输出结果为2。有一点可以明确,我的回答都是错误的。那好吧,下面是我查 阅读全文

posted @ 2012-12-07 11:17 hazir 阅读(9168) 评论(3) 推荐(1) 编辑

建立自己的函数调用帧
摘要:本文从最简单的打印“hello world!”的C程序开始,写出其汇编程序(在汇编中使用C库函数),讲解怎样建立自己的函数调用帧,接着使用jmp指令替代call完成函数的调转与返回。在linux内核中这种技巧被大量使用,最后举出内核中使用到的两个实例。首先,下面的C程序完成的功能,相信大家学大多数语言,都是用来讲解的第一个示例://helloworld1.c#include <stdio.h>int main(){ printf("hello world!\n"); return 0;}我们使用gcc进行编译生成可执行文件,结果如下所示:[guohl@guohl 阅读全文

posted @ 2012-11-26 21:35 hazir 阅读(1925) 评论(4) 推荐(1) 编辑

20. 协助完成“返回值优化(RVO)”
摘要:[19]最后曾提到了在函数通过传值方式(by value)返回一个对象时,不可避免地要生成一个临时对象,这会严重影响到程序的效率,如下例计算两个分式的乘积:class CRational{public: CRational(int numerator, int denominator) { this->numerator = numerator; this->denominator = denominator; } int numer() const //get numerator { return nume... 阅读全文

posted @ 2012-04-19 11:50 hazir 阅读(1852) 评论(0) 推荐(1) 编辑

19. 了解临时对象的来源
摘要:什么是临时对象? C++真正的临时对象是不可见的匿名对象,不会出现在你的源码中,但是程序在运行时确实生成了这样的对象.通常出现在以下两种情况:(1)为了使函数调用成功而进行隐式类型转换的时候。 传递某对象给一个函数,而其类型与函数的形参类型不同时,如果可以通过隐式转化的话可以使函数调用成功,那么此时会通过构造函数生成一个临时对象,当函数返回时临时对象即自动销毁。如下例://计算字符ch在字符串str中出现的次数int countChar (const string& str, char ch);char buffer[];char c;//调用上面的函数countChar (buffe 阅读全文

posted @ 2012-04-18 23:09 hazir 阅读(3306) 评论(2) 推荐(1) 编辑

7. 千万不要重载&& ,|| 和,操作符
摘要:C/C++语言对于逻辑表达式具有“逻辑短路”的性质,即一旦确定了真假值,表达式中即使有尚未检查的部分,都将返回。如:char *p;if ((p != NULL) && printf("%c", *p)) ... //(1) int rangeCheck(int index){ if ((index < lowerBound) || (index > upperBound)) ... //(2) ...}(1)中你不用担心p为NULL时,调用printf函数会出现错误,因为一旦p为NULL逻辑与的检测将返回FASLE,无需计算后面... 阅读全文

posted @ 2012-04-16 17:38 hazir 阅读(2064) 评论(1) 推荐(1) 编辑

6. 区别increment/decrement操作符的前置(prefix)和后置(postfix)形式
摘要:C++中允许++ 和-- 操作符的前置和后置两种形式具有重载的能力。而重载是以参数类型来区分的,然而不论是++ 还是 -- 的前置或后置均没有参数,为了区分这两种不同的操作,只好让后置式有一个int自变量,并且在它调用的时候,编译器默认给该int指定一个0值。下面的例子是使char型也能进行++ 和 -- 的运算:class Char{public: Char(char); Char& operator++ (); //前置式++ const Char operator++ (int); //后置式++ Char& ope... 阅读全文

posted @ 2012-04-16 16:27 hazir 阅读(3129) 评论(4) 推荐(2) 编辑

8. 了解各种不同意义的new 和 delete
摘要:C++中关于new 的形态主要有三种:new operator, operator new, placement new三者的用法有着不同,注意区别适用的条件:new operator:new 操作符,和C++语言其它操作符(如+, -, ->, ::....)一样,是由语言内建的,总是完成相同的事情,程序员不能改变其意义。如下为new的一种用法:string *ps = new string("hazirguo");它主要完成的任务包括三个方面:分配足够的内存,用来放置某类型对象。上例中分配足够放置一个string对象的内存。调用一个constructor,为分配的 阅读全文

posted @ 2012-04-15 14:15 hazir 阅读(473) 评论(0) 推荐(2) 编辑

2. 最好使用C++转型操作符
摘要:旧式的C转型方式,几乎允许你将任何类型转换为任何其它类型,有其自身的缺陷,表现在以下两方面:不能更精确地指明其转型的意图。如将一个pointer-to-base-class-object 转型为一个pointer-to-derived-class-object(改变一个对象的类型)和将一个pointer-to-const-object转型为一个pointer-to-non-const-object(改变对象的常量性),在旧式C语法中并不区分。难以辨识。旧式C转型方式的语法为(type)expression,由一对小括号加上一个对象名称组成,而这种语法结构在C++的任何地方都有可能使用,这就无法 阅读全文

posted @ 2012-04-14 17:58 hazir 阅读(1342) 评论(1) 推荐(2) 编辑

1.仔细区别pointers 和 references
摘要:没有所谓的null reference: 若有一个变量有可能代表一个对象,也可能不代表任何对象,应该使用pointer; 如果这个变量必须代表一个对象,即不允许这个变量为null,则应该使用reference。 因此,reference必须要有初始化,但pointer就没有此限制(不过,无初始化的pointer风险很高)。string &rs; // error! not initialstring s("hazirguo");string &rs = s; // right! rs refere to spointers可以被重新赋值指向另一个对象,ref 阅读全文

posted @ 2012-04-14 16:42 hazir 阅读(459) 评论(0) 推荐(0) 编辑

深入探索C语言之结构体(struct)
摘要:结构(struct)就是一种把一些数据项组合在一起的数据结构,其他语言把它称做为记录(record)。语法为将需要组合的内容放在花括号中,前面加上一个关键字struct,如下:struct{内容...};1.怎样定义结构体变量:举个具体的例子,如将在校学生的信息定义为一个结构体,信息内容包括学生的姓名(string)、学号(long)、年龄(int)等,就可以声明如下:struct { char sName[10]; long sNo; int sAge; };结构体本质是一种数据类型,和C语言的内置内型(char,int,long...)类似,我们可以用它来定义变量,如定义一个学生Ja... 阅读全文

posted @ 2012-04-11 15:34 hazir 阅读(972) 评论(0) 推荐(0) 编辑

一个代码可以创造一个世界,也可以毁灭一个世界!

点击右上角即可分享
微信分享提示