记得我在几年前看到过一个面试的题目,如何不引入额外的变量,实现两个数交换的函数,当时觉得不可思议,按照传统的做法:
swap的代码应该是:
void swap1(int *a,int *b)
{
int c;
c=*a;
*a=*b;
*b=c;
}
怎么不使用c这个变量来实现swap呢?现在看来好像是一个脑筋急转弯的问题,类似怎么只挪动一根火柴让等式成立之类的游戏。
看下面这个swap函数:
void swap2(int *a,int *b)恩,应该是没有引入外部变量。
{
*a=*a-*b;
*b=*a+*b; // a-b+b=a
*a=*b-*a; // a-(a-b)=a-a+b=b
}
更深入一步,我们来看看这两个函数编译成汇编语言的的结果(gcc -O2 -S):
swap1:
pushl %ebp
movl %esp, %ebp
movl 8(%ebp), %edx
movl 12(%ebp), %ecx
pushl %ebx
movl (%edx), %ebx
movl (%ecx), %eax
movl %eax, (%edx)
movl %ebx, (%ecx)
popl %ebx
popl %ebp
ret
swap2:
pushl %ebp
movl %esp, %ebp
movl 8(%ebp), %ecx
movl 12(%ebp), %edx
movl (%ecx), %eax
subl (%edx), %eax
movl %eax, (%ecx)
addl (%edx), %eax
movl %eax, (%edx)
subl (%ecx), %eax
movl %eax, (%ecx)
popl %ebp
ret
对比一下,swap2在汇编语言里面确实节省了一个寄存器ebx的使用。
然后看看怎么动态加载shared object(就是俗称的 嗖文件):
#include
#include
#include
#include
int main()
{
char *so="./swap.so";
void *hdl=dlopen(so,RTLD_LAZY);
if(!hdl) exit(1);
void (*f)(int *,int *);
f=dlsym(hdl,"swap");
if(!f) exit(2);
int a=2,b=3;
printf("a=%d,b=%d\n",a,b);
(*f)(&a,&b);
printf("a=%d,b=%d\n",a,b);
}
这样做的一个主要用途就是方便对程序进行扩展,比如MySQL的udf扩展,比如PHP的扩展,比如csf的扩展等等。
以上几个小技巧都是我感觉比较有意思的,也是曾经让我很迷惑的,再次分享给大家,有错误的地方,还请大家指正。