Month: September 2011

静态链接库

静态链接库

几个例子,使用和建立静态库的时候的几种常见情景。

首先建几个文件
a.h

void testA();

a.c

#include "a.h"

void testA() {
    printf("A");
}

b.h

void testB();

b.c

#include "b.h"
#include "a.h"

void testB(){
    testA();
    printf("B");
}
  1. 得到目标文件
  2. $gcc -c a.c
    
    $gcc -c b.c
    
  3. 得到静态库文件
  4. $ ar -r libba.a a.o b.o
    
    $ ar -r liba.a a.o
    
    $ ar -r libb.a b.o
    

得到了库libba.a libb.a liba.a

这是最终需要完成的程序。
test.c

#include "b.h"
void main()
{
    testB();
}

假设我们没有a.c,b.c这两个源文件。
在这种情况下,为了编译test.c得到可执行文件,至少需要那些文件?

由于b.h中包含了a.h,所以两个头文件都是需要的。

  1. 用libba.a
  2. $ gcc test.c -o test -L. -lba
    

    我们需要的是testB()和testA()的实现,libba.a里显然有这些实现,所以是可行的。

  3. 用libb.a 和 liba.a
  4. $ gcc test.c -o test -L. -lb -la
    

如果一开始就没有a.c,怎么办?
假设liba.a是一个第三方的闭源库,我们只有liba.a和a.h
当然,为了得到test这个可执行文件,我们也可以使用上面第二种方式编译。

如果我们不是要得到test,而是要为其它人提供libb.a怎么办?
上面的libb.a只含有testB()的实现,而没有testA()的实现。
除非“其它人”也有liba.a,否则只用libb.a是没有办法使用testB()这个函数的。

那么是不是可以把liba.a链入libb.a?
对于静态库来说,是可以的。这也就是我们的解决办法。
-r 告诉Linker进行增量式链接,得到二进制目标文件,而不是最终的可执行文件。

$ ar -r libnba.a ba.o

这个libnba.a和前面通过

$ ar -r libba.a a.o b.o

得到的libba.a应该是一样的。

这时我们就可以把libnba.a提供给”其它人”了。

$ gcc test.c -o test -L. -lnba

可以得到test可执行文件。

[Vim]vim的几种模式和按键映射

Map是Vim强大的一个重要原因,可以自定义各种快捷键,用起来自然得心应手。
vim里最基本的map用法也就是

:map c a

这里把c映射成了a,在map生效的情况下,按下c就等同于按下了a
当然,常用的Ctrl,Shift,Alt自然也是支持的。

  • 令Ctrl+a对应到a
  • :map  a
    
  • 令Alt+a对应到a
  • :map  a
    
  • 令Ctrl+Alt+a对应到a
  • :map  a
    

到此,我们已经可以做很多事情了。
但是map命令远不只这一种,在不同的模式下,同一组按键可以被映射到不同的组合上。
Vim的模式众多,但是一般被提及的也就是这么几种:

  1. Normal Mode
  2. 也就是最一般的普通模式,默认进入vim之后,处于这种模式。

  3. Visual Mode
  4. 一般译作可视模式,在这种模式下选定一些字符、行、多列。
    在普通模式下,可以按v进入。

  5. Insert Mode
  6. 插入模式,其实就是指处在编辑输入的状态。普通模式下,可以按i进入。

  7. Select Mode
  8. 在gvim下常用的模式,可以叫作选择模式吧。用鼠标拖选区域的时候,就进入了选择模式。
    和可视模式不同的是,在这个模式下,选择完了高亮区域后,敲任何按键就直接输入并替换选择的文本了。
    和windows下的编辑器选定编辑的效果一致。普通模式下,可以按gh进入。

  9. Command-Line/Ex Mode
  10. 就叫命令行模式和Ex模式吧。两者略有不同,普通模式下按冒号(:)进入Command-Line模式,可以输入各种命令,
    使用vim的各种强大功能。普通模式下按Q进入Ex模式,其实就是多行的Command-Line模式。

对于Map,有几个基本的概念

  • 命令的组合
  • 同Vim下的其他命令一样,命令的名字往往由好几段组成。前缀作为命令本身的修饰符,微调命令的效果。
    对于map而言,可能有这么几种前缀

    1. nore
    2. 表示非递归,见下面的介绍

    3. n
    4. 表示在普通模式下生效

    5. v
    6. 表示在可视模式下生效

    7. i
    8. 表示在插入模式下生效

    9. c
    10. 表示在命令行模式下生效

  • Recursive Mapping
  • 递归的映射。其实很好理解,也就是如果键a被映射成了b,c又被映射成了a,如果映射是递归的,那么c就被映射成了b。

    :map a b
    :map c a
    

    对于c效果等同于

    :map c b
    

    默认的map就是递归的。如果遇到[nore]这种前缀,比如:noremap,就表示这种map是非递归的。

  • unmap
  • unmap后面跟着一个按键组合,表示删除这个映射。

    :unmap c
    

    那么在map生效模式下,c不再被映射到a上。

    同样,unmap可以加各种前缀,表示影响到的模式。

  • mapclear
  • mapclear直接清除相关模式下的所有映射。
    同样,mapclear可以加各种前缀,表示影响到的模式。

这里列出常用的一些map命令,默认map命令影响到普通模式和可视模式。

:map :noremap :unmap :mapclear
:nmap :nnoremap :nunmap :nmapclear
:vmap :vnoremap :vunmap :vmapclear
:imap :inoremap :iunmap :imapclear
:cmap :cnoremap :cunmap :cmapclear

可以试试这些命令

  1. 命令行模式下建一个mapping
     nmap b a 
  2. 现在普通模式下,按b,可以进入插入模式,随便输入一些字符
  3. 命令行模式下建一个mapping
     vmap b d 
  4. 现在普通模式下,按V,进入了可视模式,并且选定了一整行,按下b,可以删除整行
  5. 命令行模式下建一个mapping
     imap b a 
  6. 现在试着给正在编辑的这个文件输入一个字符”b”吧 :p
  7. 命令行模式下建一个mapping
     cmap b c 
  8. 命令行模式下, 按下b,会出来一个a

好了,到此vim的按键已经被你弄得乱七八糟了,试着用unmap和mapclear清除这些mapping吧。:]

[iOS]关于IBOutlet

为了使用Interface Builder,我们需要在如XXViewController.h中增加IBOutlet标记。
IBOutlet对于编译器而言只是一个标记,也就是说,编译器会忽略这个关键字。
Interface Builder则是根据IBOutlet来寻找可以在Builder里操作的成员变量。

需要注意的是,任何一个被声明为IBOutlet并且在Interface Builder里被连接到一个UI组件的成员变量,会被额外retain一次。
常见的情形如

IBOutlet UILabel *label;

这个label在Interface Builder里被连接到一个UILabel。此时,这个label的retainCount为2。
所以,只要使用了IBOutlet变量,一定需要在dealloc或者viewDidUnload里release这个变量。