const在C,尤其是C++,是个老生常谈的问题,但这里不谈const具体有哪些特性,如何使用,而是说说const在C和C++中的区别。编译器,C使用gcc,C++使用g++,其它编译器(cl等)请自行验证。
  在我的印象中,const就是常量constant)。但这并不是真的。在C中,const仅仅表示其所修饰对象不可修改。常量和所谓“不可修改”有什么区别呢?C中,const int N = 10; 这样的语句声明了一个整型数据,声明之后你不能再为其赋值,此即为不可修改。但在C中,N却不是常量,而诸如372, 3.72, ‘A’之类才是常量,在C中定义常量通常使用#define。而在C++中,const int N = 10; 就会定义N为常量。
  怎么证明呢?你可能知道,定义静态数组,必须使用整型常量指定其大小,那咱们就用这个特性来验证上面描述的观点。

1
2
3
4
5
6
7
int
main(int argc, char **argv)
{
    const int N = 10;
    int a[N] = { 1, 2, 3 };
    return 0;
}
Tags: .

volatile

  可能很多人都没用过C/C++中的这个关键词,甚至不知道它的存在,本人以前也只是有所耳闻,但似懂非懂。
  这是一个类型修饰符,位置同conststatic等。一个使用volatile修饰的变量,比如volatile int i; 每次对该变量的直接引用,都会访问内存,而不是从寄存器中读取(如果其已经在寄存器中)。这样一来,volatile似乎没什么用处,反倒会使数据的读取相对变慢很多。但是,如果没有volatile,编译器可能会优化你的程序,使得数据从寄存器中读取,从而加快程序的运行,但如果这个变量是同其它进程/线程共享的,就可能造成数据的不一致。多线程情况下,你可以使用互斥机制来保证对共享数据访问的原子性。但是,在单片机等嵌入式环境中,硬件经常不会有这种互斥机制的支持,这时某些共享的数据(比如端口)就可能会产生不一致的情况。而使用volatile就会使编译器不对代码进行优化,每次对该变量的访问都会从内存中读取。
  下面通过观察使用volatile前后编译产生的汇编代码的不同,来加深对volatile关键词的理解。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[ ... ]
main:
[ ... ]
	call	foo # 调用函数foo,返回值保存至寄存器eax
	movl	%eax, 44(%esp) # 为i赋值
	movl	44(%esp), %edx # 读取i值
	movl	44(%esp), %ecx # 读取i值
	movl	44(%esp), %eax # 读取i值
	movl	%ecx, 16(%esp) # 参数k入栈,使用i值
	movl	%edx, 12(%esp) # 参数j入栈,使用i值
	movl	%eax, 8(%esp) # 参数i入栈
	movl	$.LC0, 4(%esp) # 格式字符串地址入栈
	call	__printf_chk
	movl	$0, %eax
	leave
	ret
[ ... ]
Tags: ,.

  现在再推荐一个类似的工具集Gow(GNU On Windows). 这是一个轻量级的Cygwin“替代品”,集成了130个Linux命令,可以由Windows Installer方便地安装,自动设定环境变量。同时,自动为Windows Explorer的右键菜单添加一个“open in cmd prompt”的菜单项。里面有特色的工具主要有:

  • 脚本解释器:bash, zsh ;
  • 归档、压缩工具:tar, gzip, bzip2等;
  • putty工具集: putty, psftp, pscp, plink等;
  • 下载工具:cURL, wget;
  • 编辑器:Vim;
  • 文本搜索/查看工具:grep, cat, less, head, tail等;
  • 文件(系统)相关工具:mv, cp, ls, rm, pwd等;

  另外,你可能注意到,Gow中并没有gcc(GNU Compiler Collections),所以,如果你需要这些工具,你可能还需要安装上面的cygnus。需要注意的是,这两个工具集的命令有交集,所以同时安装这两个工具集时要注意PATH中搜索路径的顺序,我更倾向于把Gow的bin放在前面。
  最后,如果你系统中已经装有Vim(通常为较高的版本),最好把Gow中提供的Vim(貌似是6.3)删除。

Tags: ,.

chmod命令介绍

  下面介绍如何使用chmod命令来设定和修改文件的权限位。
  首先,chmod命令本身的执行也有限制,普通用户只能修改自己的文件的权限位,超级用户可以使用chmod修改任意用户任意文件的权限。使用chmod的方法为chmod [option] mode file. 常用的选项就是-R,用来对整个目录及其子目录中的文件进行模式(权限)修改。mode可以由两种方式指定,一种是由字母表达式表示的相对修改方式,一种是以4位8进制表示的绝对方式。
  第一种方式:chmod [ugoa][+-=][rwxst] file. u指代user,g指代group,o指代other,a指代all。+-=分别执行指代增加、减少、设定相应权限(由后面的参数指定)。rwxst分别指代读、写、执行、set-user-id/set-group-id、sticky-bit粘滞位。整体上理解,就是对哪类用户(ugoa,为a时可省略)执行哪些权限(rwxst)的什么修改(+-=)。示例:

1
2
3
4
5
6
7
8
9
10
11
12
$ chmod u-x a.out 
$ ll a.out
-rw-r-xr-x 1 dutor dutor 7.1K 2010-08-08 13:33 a.out
$ chmod +t a.out 
$ ll a.out
-rw-r-xr-t 1 dutor dutor 7.1K 2010-08-08 13:33 a.out
$ chmod g=rs a.out 
$ ll a.out
-rw-r-Sr-t 1 dutor dutor 7.1K 2010-08-08 13:33 a.out
$ chmod a+x a.out 
$ ll a.out
-rwxr-sr-t 1 dutor dutor 7.1K 2010-08-08 13:33 a.out
Tags: ,,.

  这款插件叫Mumbless,思路来源于我以前使用的插件block-spam-by-math。刚刚写好,可能还不太完善,但以最近一周的使用来看,还未出现自动的垃圾留言,或许因为小众吧。如果你需要,可以点击此处下载Mumbless.zip。安装方法同其它插件。
  为了更有效地利用这款小插件,这里提供些建议:

  • Mumless.php文件中Mumbless类中的add_check_form函数中的keywords数组包含了候选的验证码,你可以根据自己的喜好增删改;
  • 验证码输入框可能会影响原有表单的tabindex顺序,你可以根据需要调整;
  • 验证码图片的大小、样式在keyimg.php文件中定义,必要时你也可以对某些参数进行修改。

  希望这个插件能为你节省些许删除垃圾评论的时间。

Tags: .

配置inputrc

  我们这里需要的是一种叫做菜单式补全(menu-complete)的功能。通常,默认情况下,这个选项是没有被配置的。为了配置这项功能,并为之进行快捷键绑定,我们需要修改inputrc配置文件,这个文件中保存了Readline的一些键绑定和其它诸如编辑模式的配置选项。像许多其它配置文件一样,inputrc有系统级的配置选项/etc/inputrc和用户级的点文件~/.inputrc。建议建立自己的点文件,而不是直接编辑系统级文件,当然如果整个系统只是你一个人在用的话,你也可以在/etc/inputrc上面直接编辑。但使用点文件的另一个好处告诉你,它是属于你自己的,即使在另外一个不同的发行版上,点文件通常也是可以直接使用的。这可以减轻你在不同系统上的不适。
  好了,打开或者建立你的.inputrc,写下,下面两行:

1
2
"\C-j": menu-complete
"\C-k": menu-complete-backward
Tags: ,,.

  对qsort需要注意几点:

  • qsort中第一个参数是待排序数组的开始地址,既然是数组,各元素就是同类型、同大小的对象,且数组是“一维数组”(即地址是连续的);
  • qsort用以区分对象的依据是第二和第三个参数,分别表示对象个数和每个对象的大小(字节);
  • qsort并不知道每个对象的类型和结构,排序准则由用户在第四个参数(比较函数)中指出,qsort按该比较函数准则的“升序”对数组进行排序;
  • 标准C不支持运算符重载,各对象的交换(因为这是qsort)靠的是逐字节的拷贝(memcpy?)。

  在上面的两片代码中,待排序的对象一个是字符型指针,一个是char (*)[10]型数组。然后,就没有然后了。

Tags: ,,.

动态链接库

  动态库和静态库相似,也是各个目标文件的集合。但相比静态链接的程序,动态链接可执行程序要小得多:这类程序运行时需要外部共享 函数库的支持,因此好像并不完整。除了程序体小之外,动态链接允许程序包指定必须的库,而不必将库装入程序包内。动态链接技术还允许多个运行中的程序共享一个库,这样就不会出现同一代码的多份拷贝共占内存的情况了。由于这些原因,当前多数程序采用动态链接技术。
  在Linux中的扩展名通常为.so。但在链接时,并不会被链接到可执行文件中,而是在执行时(需要时)由操作系统的动态加载模块动态地加载到内存,并链接到可执行文件地址空间的相应位置。
  动态链接库的创建也分为编译和”归档”两个阶段,但不同的是在这两个阶段需要使用一些不同的命令选项。首先,需要将源文件编译成一种成为位置无关码(PIC: Position Independent Code)的目标文件,这种代码可以被加入到内存的任何位置却不需要加载器对其进行重定位,关于这种格式可以参考《链接器与加载器》和《程序员的自我修养–链接装载与库》中较为详尽的描述。接下来需要将这些位置无关码“归档”为.so文件。整个过程只需一个工具即可,即gcc。还是上面的源文件,执行以下命令:

1
2
$ cc -c -fpic plus.c sub.c
$ cc -shared -o libmath.so *.o
Tags: ,.

  find命令可以按照指定的规则对硬盘上的文件进行查找,且可以跨越不同的文件系统。find命令的使用方法:

1
find fold [option]

  下面按照不同的选项介绍find命令。

find -name

  -name是最常用的选项,它指定了需要查找的文件名的模式,模式中可以使用通配符和简单的正则表达式。下面的命令查找Wdir目录下的.cpp文件:

1
2
3
4
5
6
7
8
9
10
11
dutor@dutor-desktop:~$ find Wdir -name "*.cpp"
Wdir/Cpp/Pthread/main.cpp
Wdir/Cpp/STL/sort_list.cpp
Wdir/Cpp/STL/Heap.cpp
Wdir/Cpp/STL/operator.cpp
Wdir/Cpp/STL/bind2nd/main.cpp
Wdir/Cpp/STL/Kth-Max.cpp
Wdir/Cpp/STL/priority_queue.cpp
Wdir/Cpp/ACM/Huffman/main.cpp
Wdir/Cpp/ACM/Bellman-Ford/main.cpp
......

  需要注意的是,如果搜索目录以相对路径形式指定,则搜索结果也以相对路径形式给出;否则,搜索结果以绝对路径形式给出。

Tags: ,.

  我的台式机,以前用的键盘一直是PS/2接口的,前些天换了个USB口的。一直没发现问题,知道昨天想进Windows办点私事儿,才发觉在Grub里面,无法用键盘选择操作系统,只能进入默认的Linux。
  起初怀疑是操作系统的驱动问题,但马上就排除了,因为Grub引导阶段,OS还没有降生呢!
  接下来就是Grub了,但大名鼎鼎的Grub怎会不支持USB键盘呢。
  最后需要考虑的就是BIOS了,键盘鼠标之类的简单硬件都由它来控制。进入BIOS,果然后USB Keyboard的使能选项,选择Enable,重启,问题解决了。
  记住,还有个BIOS。

Tags: .