C/C++


计算二进制整数中含有的1的个数的奇偶性

Table of Contents 问题描述 解决方案 问题描述 遇到过一个问题:判断一个数的二进制表示中含有的1的个数是偶数的还是奇数的。按照之前的做法,我会写一个循环,然后挨个判断这个数中每个位,记录下其中值为“1”的位的个数,最后给出结果。这种方法简单、直接,效率嘛,一般般,也没什么不好的。这两天在看《深入理解计算机系统》,其中有一道习题就是这个问题,而且还限制了不能用条件语句和循环语句来实现。这下,我就傻眼了。 解决方案 自己想了半天还是没有想到解决方案,不得以只能向Google求救,功夫不负有心人,总算让我找到解决方案了: /* Return 1 when x contains an odd number of 1s; 0 otherwise. Assume w=32. */ int odd_ones(unsigned x) { /* assume type unsigned take place 4 bytes */ x = (x >> 16) ^ x; x = (x >> 8) […]


配置Emacs为C/C++开发环境:安装配置cedet

Table of Contents 犯罪动机 源代码下载 编译cedet 配置 替换内置的cedet 其他的配置 安装配置ecb 使用过程中遇到的问题 鼠标,又见鼠标 犯罪动机 刚开始使用Emacs时,也有找过cedet的相关资料,只是当时还不怎么用Emacs来写C/C++代码,所以只是浅尝辄止,也可以说几乎就没弄。渐渐熟悉了Emacs,在上面写代码的频率也高了,于是又重新拾起cedet。 由于使用的是Emacs24,里面已经自带了cedet,起初认为自带了更好,不用折腾。等到真正查资料要配置时,才发现根本不是那么回事。比如网上配置cedet的帖子中,常常会提到semantic-load-enable-minimum-features等设置函数,可是无论我怎么搞(加require ‘cedet,加semantic/canned-configs等),就是不行,一直出错。实在不行了,就跑到/usr/local/share/emacs/(我是用brew装的Emacs)下用find命令去抓semantic-load-enable-minimum-features这个串,结果还是没抓着,于是确定是Emacs内置的cedet并不包含这部分实现。起初还以为是OSX下的Emacs的问题,后来跑到Ubuntu下试,一样一样的!于是找啊找啊,总算找到为什么:semantic-load-enable-minimum-features这种设置方式,不符合minor-mode的规范,因此去掉了。邮件中还提到其他的几点改动,包括部分去除调试功能,使用的cedet版本较老等。 考虑了一下,还是觉得内置的版本不爽,于是决定折腾折腾自己,到官网上下载来编译安装。 源代码下载 这个很简单,Google一下,马上知道。到cedet的官网源码下载页上找到下载地址,使用bzr或者git下载即可: bzr checkout bzr://cedet.bzr.sourceforge.net/bzrroot/cedet/code/trunk cedet 为了方便,我在.emacs.d中建了一个3rd-party的文件夹,将cedet的源码直接下载到了这个目录下。 编译cedet 编译过程相对简单,也很顺利: # cd cedet make EMACS=/usr/local/bin/emacs-24.3 # optional to compile cedet/contrib: cd contirb make EMACS=/usr/local/bin/emacs-24.3 上面脚本首先进入cedet目录中编译cedet的标准模块,而后(可选)进入contrib子目录,编译其他不符合FSF协议的模块。 配置 替换内置的cedet 由于Emacs24内置了cedet,因此要尽早载入外部的版本(比如在.emacs的开头),避免由于Emacs已载入内置的eieio(cedet中的基础模块)而导致我们的cedet无法载入的问题。 ;; load cedet. It is very […]


配置Emacs为C/C++开发环境:识别不同文件夹中的头文件

作为一个不折不扣的码农,Emacs最重要的功能就是要能够帮助我提升写代码的效率,其中我认为很重要的功能有两个,一个是代码补全,另一个则是语法检查。对于代码补全,我使用的是auto-complete配合auto-complete-clang-async;而语法检查使用的是flycheck配合clang,用起来很爽。刚开始写一些小的C/C++程序,头文件和源文件都是放在同一级目录下的,这种情况下auto-complete-clang-async和flycheck工作得都很好。但是好景不长,项目一旦稍微复杂起来,就会分不同的目录,而包含的头文件总不可避免地会在不同目录下,结果由于找不到头文件,导致auto-complete-clang-async和flycheck双双失效了:由于头文件都是放在文件最开始的,由于没有指定头文件所在的路径,clang解析include指令时会因找不到文件而出错,停止解析。这样,后续源码中如果出现其他错误,或者需要自动补全时,就不会有任何提示了,Emacs几乎退化成了一个普通的代码编辑器了! Google了好长时间,刚开始还寄希望于cedet和ede之类的,始终没有结论,没法解决这个问题。后来,极度郁闷中时,峰回路转,脑子终于开了点窍:我在意的压根不在于项目管理,而在于补全和语法检查功能。而且Emacs中各个扩展大都是各自为战的,即便搞定了项目管理的配置,也极有可能搞不定这两个核心功能! 于是屁颠屁颠回到原点,重新查找auto-complete-clang-async和flycheck中关于头文件的配置。明确了目标和方向,很快就有了眉目: 在flycheck中,可以通过flycheck-clang-include-path来添加/指定要搜索的头文件路径 在auto-complete-clang-async中,可以通过设置ac-clang-cflags来添加头文件路径 思路有了,那么具体的设置方法呢?别急,我一一道来(假设头文件路径为./include): 直接设置法:打开要编辑的源文件,然后执行M-x eval-expression,之后在mini-buffer中输入(add-to-list ‘flycheck-clang-include-path “include”),然后再执行一次eval-expression,执行(add-to-list ‘ac-clang-cflags “-Iinclude”)。如果还有其他的路径,则重复以上操作,一个一个添加进去。另外,由于这两个变量都是局部于文件的(即仅对当前buffer有效),因此当打开一个新文件时,还得重新设置。 上面的方法实在是太烦了,是地球人都受不了。为了偷懒,我决定写一点程序,在打开一个C文件时,自动判断是否存在./include,../include,./inc或者../inc目录,如果存在,就将他们添加到ac-clang-cflags和flycheck-clang-include-path中。这种实现简单粗犷,但基本满足我的需求: ;; detect and add headers path, to make flycheck and clang-complete work ; make sure flycheck-mode is enabled (global-flycheck-mode) (defun check-and-add-header-path (checkpath) “Check if CHECKPATH exists and it’s a directory, if it is a directory, then and […]


C语言中整型的减法

在C语言中,我们常常会用到加减等基本算术运算。我们知道,计算机在计算时,首先需要把数值转换成二进制,而后对二进制数进行运算。由于绝大多数机器都是使用二进制补码方式来存放整型的,因此下面讨论假设整型是以二进制补码方式表示的。二进制加法相当容易理解,简单的将各位相加,并处理好进位就可以了;对于二进制减法(为了方便叙述,这里设定整型字长为4位),则并不是那么直观了:\(0010_{2} – 0101_{2}\)(即十进制的\(2_{10} – 5_{10}\))的计算过程是怎样的呢? 实际上,在计算机中,当遇到诸如x-y这样的表达式时,并不是直接进行减法运算的,而是将其转换成形如x+(-y)这样的加法算式,而后再进行加法运算。拿上面的\(0010_{2} – 0101_{2}\)说,首先需要将\(0101_{2}\)转成其负数(-y),即转成\(1011_{2}\),然后再进行加运算,得到结果为\(1101_{2}\),即十进制数-3。 上面举的例子是有符号整数的,那么对于无符号整数,是否遵循同样的规则呢?下面我们举例来说明: int x = 5; int y = -1; unsigned z = (unsigned)x – (unsigned)y; printf(“z=%u, (int)z=%d\n”, z, (int)z); 不实际运行,自己计算一下z的值吧。 正确的答案是:z=6,你算对了吗?想知道为什么?OK,那就继续往下看吧! 首先,我们约定:对于任意整数a,ua表示a的无符号值。根据这个定义,我们可以得到:当a>=0时,ua=a;当a<0时,ua=\(a_{w-1}2^w + a\),其中w指a的字长。 对于上面代码片段中的表达式“(unsigned)x – (unsigned)y”,我们可以写成“ux – uy”,进一步的,当计算机要计算这个表达式的值时,会将其转换成“ux + (-uy)”。根据上面a与ua的关系,我们可以得到:\(ux + (-uy) = ux + (-(y_{w-1}2^w + y)) = ux + […]


C/C++中原子类型占用的空间大小

在C/C++中,基本数据类型占用的字节数(用sizeof(type)得到),在不同平台、不同编译器下可能是不同的,不像Java那样有统一的标准。长期以来我对这些具体数值并不是非常清楚,因此决定花些时间整理一下。测试使用的测试代码很简单: /* data_size.c */ #include <stdio.h> int main() { // NOTE: should use the format string “%u” when compiled with TurboC // NOTE: VC6 does not support “long long” printf(“sizeof(char): %zd, sizeof(short): %zd, sizeof(int): %zd\n”, sizeof(char), sizeof(short), sizeof(int)); printf(“sizeof(long): %zd, sizeof(long long): %zd, sizeof(void *): %zd\n”, sizeof(long), sizeof(long long), sizeof(void […]


编译参数中-pthread以及-lpthread的区别

一般情况下,我们在链接一个(文件名为libxxx.so或libxxx.a等的)库时,会使用-lxxx的方式;在Linux中要用到多线程时,需要链接pthread库,按照惯例,我们应该使用-lpthread的方式来进行链接;但是,通过日常的观察,我发现很多开源代码都是使用了-pthread参数,而非使用-lpthread,这是为什么呢? 一通Google后,总算找到一些线索: 为了可移植性:在Linux中,pthread是作为一个单独的库存在的(libpthread.so),但是在其他Unix变种中却不一定,比如在FreeBSD中是没有单独的pthread库的,因此在FreeBSD中不能使用-lpthread来链接pthread,而使用-pthread则不会存在这个问题,因为FreeBSD的编译器能正确将-pthread展开为该系统下的依赖参数。同样道理,其他不同的变种也会有这样那样的区别,如果使用-lpthread,则可能在移植到其他Unix变种中时会出现问题,为了保持较高的可移植性,我们最好还是使用-pthread(尽管这种做法未被接纳成为C标准,但已基本是事实标准)。 添加额外的标志:在多数系统中,-pthread会被展开为“-D_REENTRANT -lpthread”,即是除了链接pthread库外,还先定义了宏_REENTRANT。定义这个宏的目的,是为了打开系统头文件中的各种多线程支持分支。比如,我们常常使用的错误码标志errno,如果没有定义_REENTRANT,则实现为一个全局变量;若是定义了_REENTRANT,则会实现为每线程独有,从而避免线程竞争错误。 参考资料: https://groups.google.com/forum/#!topic/comp.programming.threads/NCEpG0EOCCY http://www.lambdacs.com/cpt/FAQ.html#Q300 Author: Rex Shen Created: 2014-03-06 Thu 08:14 Emacs 24.3.1 (Org mode 8.2.5h) Validate


C++中public、protected以及private的使用

相比C语言,C++中通过class/struct来定义既包含数据,又包含行为的结构,从而支持了“对象”。现实世界中,一个人(一个对象)通常 拥有一些资产(数据),并且掌握某些技能(行为),并且这些资产和技能通常可以分为三类: 可以与任何人分享的 有限分享的,比如留给子孙后代的财产或本领 除了自己之外谁也不能用的,比如给自己留的棺材^_^ 为了表达类似的概念,在C++中使用public、protected以及private,分别代表可任意分享的、有限分享的以及独享的。比现实世界稍微复杂些,在C++中这三个关键字不仅可以修饰类成员,还可以修饰类的继承关系。 当这三个关键字用在类成员时: class Base { public: void publicMethod() { cout << “Begin of ” << __FUNCTION__ << endl; cout << “End of ” << __FUNCTION__ << endl; } static void staticPublicMethod(Base* obj) { // just call this class’s static private method staticPrivateMethod(obj); } int getProperty() […]