KEEP K.I.S.S.

tk's blog

do ... while(0) 的使用

今天稍微看了下 Ruby 的 array#pack 和 string#unpack 的实现,额,相当复杂(因为 lua 标准库里没有这样的函数实现,所以看 Ruby 的)。然后在其中发现了很多宏定义使用了

#define MACRO(x) do {\
statements; \
} while(0)

这样的形式,蓝后就去百度谷歌看了看,这里就贴链接,不重复解释了,反正是妙用。

do...while(0)的妙用                     http://www.cnblogs.com/flying_bat/archive/2008/01/18/1044693.html

do { … } while (0) what is it good for?       http://stackoverflow.com/questions/257418/do-while-0-what-is-it-good-for

Merry Christmas Mr. Lawrence

Merry Christmas Mr. Lawrence

强过千言万语

 

无聊写的谷歌拼音颜文字扩展

谷歌输入法的颜文字扩展已经有好多了,反正也不差我再写一个吧 o(* ̄▽ ̄*)o ,表情比较多(300+)

源码和扩展文件都放在 Github 上了:https://github.com/tisyang/kaos

示例1:

示例2:

 

安装方法:
在谷歌输入法设置的 扩展 页面,选择 安装扩展包 ,选择下载的 kaos.lua 文件即可。
安装后需要重启输入法,也就是关闭输入法然后再开启。
 
 
 
更新历史:
      2. 当一个拼音对应多个表情时,现在可以随机返回其中的一个,2012-06-06
      1. 修正潜在的 Lua 关键字冲突问题,2012-06-05
 
已知问题:
      1. 候选的表情总是在候选列表最后,这是谷歌输入法本身的设置所致
      2. 某些拼音对应多个表情,但是目前谷歌输入法只能显示第一个

 

setjmp/longjmp 使用注意

  1. 不应从调用 setjmp() 的过程中返回。
    如果setjmp所在的函数已经调用返回了,那么longjmp 使用该处 setjmp 所填写的对应 jmp_buf 缓冲区将不再有效。这是因为longjmp 所要返回的"栈帧"(stack frame) 已经不再存在了,程序返回到一个不再存在的执行点,很可能覆盖或者弄坏程序栈。
    上篇文章叙述过这个,也可以参见:setjmp 的正确使用
     
  2. 保证局部变量在 longjmp 过程中一直保持它的值的唯一可靠方法是把它声明为 volatile (这使用于那些值在 setjmp 执行和longjmp 返回之间会改变的变量) 详细可以参见:setjmp 和 longjmp,以及对变量的影响 

    简单来说如下:
    1. 优化不影响 global, static, volatile 变量。
    2. 标出来的那句话意思是,保存在内存中的变量,longjmp返回后,保持了longjmp时的值。
        而在 cpu 中的值将会退回到setjmp时的值。
    3. 没有优化时global, static, volatile, auto, register都存在内存中。
        返回的时候,这些值仍然是longjmp时候的值。
        但在有优化的时候, auto, register的值是在寄存器的。
        所以返回的时候,这两个值是在setjmp时候的值。
     
  3. 编程的惯用法: if( setjmp(x) ){/* handle longjmp(x) */}。
     
  4. 仅在特定范围内引用 setjmp 。

setjmp 和 longjmp

本文主要讲解 C 库中的函数 setjmp 和 longjmp,也就是所谓的 非局部跳转。

本文主要翻译和出自 Jim Plank 的讲座 CS360 Lecture notes -- Setjmp

翻译 by tisyang 自我感觉不直观的翻译都在括号中附加了原文


setjmp()/longjmp()

Setjmp() 和 longjmp() 是在 C/Unix 下用于执行复杂控制流的子程序。

理解 setjmp() 和 longjmp() 的关键之一就在于理解 机器布局(machine layout), 这个在几周前的 汇编和内存分配(assembler and malloc) 讲座中描述过。 一个程序的状态完全取决于它内存中的内容(contents of its memory) (比如 代码(code), 全局变量(globals), 堆(heap), 和栈(stack)), 以及寄存器中的内容。 寄存器中的内容包括 栈指针寄存器(stack pointer,缩写 sp)、帧指针寄存器(frame pointer,指向栈中一个函数的local 变量的首地址,缩写 fp)和 程序计数器寄存器(program counter,缩写 pc)。 setjmp() 所做的事情就是保存当前这些寄存器的内容以便在以后的某个时刻 longjmp() 可以恢复它们。 因此,longjmp() 可以“返回” 到 setjmp()被调用时刻的程序的状态。

具体来看:

#include < setjmp.h >
int setjmp(jmp_buf env);

这是将当前寄存器的状态保存到 env 中。 如果打开 /usr/include/setjmp.h, 你将看到 jmp_buf 的定义如下:

#define _JBLEN  9
typedef struct { int _jb[_JBLEN + 1]; } jmp_buf[1];

这说明 jmp_buf 是一个包含数量为 _JBLEN+1 的整数数组。

因此, 当调用 setjmp() 时,传递的参数是这样一个整数数组的地址,接着函数把所有寄存器的值保存到这个数组之中。在这种情况下调用, setjmp() 会返回 0。

longjmp(jmp_buf env, int val);

Longjmp() 会将寄存器重置为保存在 env 中的值 ,这包括 spfp 以及 pc这意味着 longjmp() 函数不会返回。 相反, 当调用 longjmp() 时,程序流会返回到好像刚刚调用完 setjmp() (保存了 env )一样。 这是因为 pc(程序计数器)和其他寄存器的内容都被一起恢复了。此时,setjmp() 会返回传递给 longjmp() 的参数 val 的值,注意 val 的值不允许为 0 (请参阅 man 帮助系统)。因此,当 longjmp() 被调用时,setjmp() 会返回一个非0值, 程序流也从 setjmp() 中返回。

用一个示例来说明,看如下的代码 (in sj1.c):