shootingstars

菩提本无树,明镜亦非台。本来无一物,何处惹尘埃。尘埃乃虚幻,亦何惧之来?

  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
  24 随笔 :: 0 文章 :: 35 评论 :: 0 Trackbacks

2008年7月22日 #

int _stdcall s_addint(int i, int j)
{
    printf(
"i = %d\n",i);
    printf(
"j = %d\n",j);
    
return i+j;
}


int __cdecl  c_addint(int i, int j)
{
    printf(
"i = %d\n",i);
    printf(
"j = %d\n",j);
    
return i+j;
}


int _fastcall  f_addint(int i, int j, int k)
{
    printf(
"i = %d\n",i);
    printf(
"j = %d\n",j);
    printf(
"k = %d\n",k);
    
return i+j+k;
}


int _tmain(int argc, _TCHAR* argv[])
{
    
int num;

    
// 汇编调用_stdcall函数
    
// 参数由右至左压栈
    
// 调用返回时,堆栈由被调函数调整
    
// 返回值在EAX中
    _asm
    
{
        push 
2
        push 
1
        call s_addint
        mov  num,eax
    }


    printf(
"num = %d\n",num);

    
// 汇编调用__cdecl函数
    
// 参数由右至左压栈
    
// 调用返回时,堆栈由调用者调整
    
// 返回值在EAX中
    _asm
    
{
        push 
4
        push 
3
        call c_addint
        mov  num,eax
        add esp,
4*2
    }


    printf(
"num = %d\n",num);

    
// 汇编调用_fastcall函数
    
// 函数的第一个和第二个DWORD参数(或者尺寸更小的)通过ecx和edx传递,其他参数通过从右向左的顺序压栈
    
// 调用返回时,堆栈由被调函数调整
    
// 返回值在EAX中
    _asm
    
{
        mov ecx,
5
        mov edx,
6
        push 
7
        call f_addint
        mov  num,eax
    }


    printf(
"num = %d\n",num);
    
    
return 0;

}

 

以上代码通过VC8编译

 

posted @ 2008-07-22 13:52 shootingstars 阅读(10) | 评论 (0)编辑

2008年6月2日 #

在Java中,继承类可以使用super访问基类中的数据变量
class A
{
    
int i = -1;
}


class B extends A
{
    
void printSuperI()
    
{
        System.out.println(
super.i);
    }

}

但是在C++中,貌似没有此类访问符。。。
能否在C++中访问基类中的数据呢?当然能够,最简单的方式莫过于在基类中定义Get/Set等属性函数,在继承类中使用即可。
问题是,变量太多,定义n多的Get/Set看着有些烦人。
呵呵,其实可以采用一种不是很正规的方式来直接访问基类中的数据(注意:在真实的项目中不建议使用此类方法,这个方法仅仅用于对C++二进制布局的了解+测试而已。我目前已经用vc8、gcc测试通过)
我们知道,在C++中,基类和继承类对象其实享用的同一块内存空间。即this指针所指位置。我们的所有数据都在this指针所指位置上,所有数据按照内存正向规则向上占用各自的位置。

例子代码:
class A
{
public:
    
int i,j;
    A()
    
{
        i 
= -1;
        j 
= -2;
    }


}
;

class B : public A
{
public:
    
void printSuperI()
    
{
        
// 此this指针及指向A::i的内存位置
        int superI = *(int *)(this);   
        
// 此this+4指针及指向A::j的内存位置(sizeof(int) == 4)
        
// 注意:此时必须知道C++的内存对齐方案,当然你可以通过命令要求按照自己的规则进行内存对齐。
        int superJ = *(int *)((char*)this+4);  
        printf(
"SuperI=%d, superJ=%d\n",superI,superJ);
    }

}
;


问题:一旦在基类中出现了虚拟函数,此时的this指针不再指向数据的第一个变量,而是指向vptr。
在此种情况下需要给this指针加上一个vptr的指针变量位置即可。
class A
{
public:
    
int i;
    A()
    
{
        i 
= -1;
    }

    
virtual void foo()
    
{
        printf(
"Foo\n");
    }


}
;

class B : public A
{
public:
    
void printSuperI()
    
{
        
int superI = *(int *)((char*)this+4);
        printf(
"SuperI=%d\n",superI);
    }

}
;


补充:
既然知道了vptr的位置,那我们可以直接手工打造函数地址来调用它(我只使用vc8调用通过,gcc调用报错。。。)
vc的c++虚拟指针手工调用
class A
{
public:
    
int i;
    
char *p;
    A()
    
{
        p 
= "5678";
        i 
= -1;
    }

    
virtual void foo(const char *s)
    
{
        printf(
"Foo, %s : %s\n",s, p);
    }

    
virtual void foo1(const char *s)
    
{
        printf(
"Foo1, %s\n",s);
    }


}
;

typedef 
void (A::*foo_fun)(const char *p);

class B : public A
{
public:
    
void printSuperI()
    
{
        unsigned 
int *vptr;
        
int superI = *(int *)((char*)this+4);
        printf(
"SuperI=%d\n",superI);
        vptr 
= (unsigned int *)this;
        foo_fun fun_ptr 
= *(foo_fun*)(*vptr);
        (
this->*fun_ptr)("1234");
        foo_fun fun_ptr1 
= *(foo_fun*)((*vptr)+4);
        (
this->*fun_ptr1)("abcd");
    }

}
;

posted @ 2008-06-02 09:23 shootingstars 阅读(21) | 评论 (0)编辑

2008年5月7日 #

编译程序一般划分为
1 词法分析 -- 输入源程序,对源程序的字符串进行扫描和分解,得到一个个单词(token)
2 语法分析 -- 按照语法规则,确定输入串是否符合此规则
3 语义分析及中间代码产生 -- 在语法分析的基础上分析含义,并且进行相关的翻译(中间代码)。如很多编译器采用“四元式”作为中间代码,四元式如下所示:
    算符    左操作数    右操作数    结果
4 优化 -- 优化以上产生的中间代码,产生更加有效的中间代码
5 目标代码生成 -- 按照目标机产生低级语言代码

前端以及后端
前端 -- 与目标机无关的部分(词法分析,语法分析,语义分析,与目标机无关的中间代码优化)
后端 -- 与目标机有关的部分(与目标机相关的中间代码优化以及目标代码生成)

posted @ 2008-05-07 18:43 shootingstars 阅读(34) | 评论 (0)编辑

2007年8月17日 #

以前使用bind1st以及bind2nd很少,后来发现这两个函数还挺好玩的,于是关心上了。
在C++ Primer对于bind函数的描述如下:

绑定器binder通过把二元函数对象的一个实参绑定到一个特殊的值上将其转换成一元函数对象

C++标准库提供了两种预定义的binder 适配器bind1st 和bind2nd 正如你所预料的bind1st 把值绑定到二元函数对象的第一个实参上bind2nd 把值绑定在第二个实参上
例如
为了计数容器中所有小于或等于10 的元素的个数我们可以这样向count_if()传递
count_if( vec.begin(), vec.end(), bind2nd( less_equal<int>(), 10 ));


哦,这倒是挺有意思的。于是依葫芦画瓢:
bool print(int i, int j) 
{
    std::cout
<< i << "---" << j << std::endl; 
    
return i>j;
}

int main(int argc, char *argv[])
{
    (std::bind1st(print, 
2))(1);
    
return 0;

}
满怀希望它能够打印
2---1

只不过。。。编译出错:
1    Error    error C2784: 'std::binder1st<_Fn2> std::bind1st(const _Fn2 &,const _Ty &)' : could not deduce template argument for 'overloaded function type' from 'overloaded function type'   
---不能够推断出模板参数for 'overloaded function type' from 'overloaded function type' 。。。。
(还真看不明白。。。)

于是直接看bind1st代码:
template<class _Fn2,
    
class _Ty> inline
    binder1st
<_Fn2> bind1st(const _Fn2& _Func, const _Ty& _Left)
        {    
        typename _Fn2::first_argument_type _Val(_Left);
        
return (std::binder1st<_Fn2>(_Func, _Val));
        }
嗯。。。在代码里

typename _Fn2::first_argument_type _Val(_Left)
说必须定义
first_argument_type类型,可是我一个函数,哪里来的这个类型定义?嗯,STL一定提供了某种东东用来自动定义这个类型。找啊找,于是找到了ptr_fun。
这个函数自动将一个函数指针转换为一个binary_function的继承类pointer_to_binary_function,而在
binary_function中定义了first_argument_type。
于是修改代码:
int main(int argc, char *argv[])
{
    (std::bind1st(std::ptr_fun(print), 
2))(1);
    
return 0;
}
打印结果如下:
2---1
posted @ 2007-08-17 17:35 shootingstars 阅读(321) | 评论 (1)编辑

2007年8月13日 #

最近公司版本管理日显复杂,急需进行每日构建来确保版本质量。于是想到了用python开发一个简单的每日构建工具进行自动代码切出,自动编译以及自动打包。

写了好几天,基本成果出来了。用一个XML文件控制所有的代码切出,编译以及打包过程。
公司的软件涉及到了C++,Java和C#,C++和C#都是用的Vs2005,这个好说,用Vs2005自带的命令行方式编译项目即可。但是Java开发用的是Eclipse,没有听说Eclipse自己带命令行方式的,同事推荐使用ANT,于是研究了以下ANT的配置方式。。。天哪。。。我写的那个每日构建工具基本上用ANT都可以实现。。。
郁闷,早知道,也没必要花好几天时间,直接拿ANT来用就好了。。。

不过好在发现自己写的东东与ANT的很多东西不谋而合,也算心里有点安慰了。

附上一个python的学习文档,俺就是看着它上手的:Python 研究(Dive Into Python)

posted @ 2007-08-13 14:41 shootingstars 阅读(168) | 评论 (0)编辑

2007年8月1日 #

七:regex_replace学习
写了个去除左侧无效字符(空格,回车,TAB)的正则表达式。
std::string testString = "    \r\n Hello        World  !  GoodBye  World\r\n";
std::
string TrimLeft = "([\\s\\r\\n\\t]*)(\\w*.*)";
boost::regex expression(TrimLeft);
testString 
= boost::regex_replace( testString, expression, "$2" );
std::cout
<< "TrimLeft:" << testString <<std::endl;
打印输出:
TrimLeft:Hello          World  !  GoodBye  World

问题是去除右侧无效字符的正则表达式该怎么写?哪位大侠显个灵,帮助写写看,多谢了。
posted @ 2007-08-01 18:45 shootingstars 阅读(255) | 评论 (2)编辑

六:关于重复的贪婪
我们先来一个例子:
std::string regstr = "(.*)(age)(.*)(\\d{2})";
boost::regex expression(regstr);
std::
string testString = "My age is 28 His age is 27";
boost::smatch what;
std::
string::const_iterator start = testString.begin();
std::
string::const_iterator end = testString.end();
while( boost::regex_search(start, end, what, expression) )
{

    std::
string name(what[1].first, what[1].second);
    std::
string age(what[4].first, what[4].second);
    std::cout
<< "Name:" << name.c_str() << std::endl;
    std::cout
<< "Age:" <<age.c_str() << std::endl;
    start 
= what[0].second;
}

我们希望得到的是打印人名,然后打印年龄。但是效果令我们大失所望:
Name:My age is 28 His
Age:27

嗯,查找原因:这是由于"+"号或者"*"号等重复符号带来的副作用,这些符号会消耗尽可能多的输入,使之是“贪婪”的。即正则表达式(.*)会匹配最长的串,而不是匹配最短的成功串。
如何使得这些重复的符号不再“贪婪”,我们在重复符号后加上"?"即可。
std::string regstr = "(.*?)(age)(.*?)(\\d{2})";
boost::regex expression(regstr);
std::
string testString = "My age is 28 His age is 27";
boost::smatch what;
std::
string::const_iterator start = testString.begin();
std::
string::const_iterator end = testString.end();
while( boost::regex_search(start, end, what, expression) )
{

    std::
string name(what[1].first, what[1].second);
    std::
string age(what[4].first, what[4].second);
    std::cout
<< "Name:" << name.c_str() << std::endl;
    std::cout
<< "Age:" <<age.c_str() << std::endl;
    start 
= what[0].second;
}
打印输出:
Name:My
Age:28
Name: His
Age:27

posted @ 2007-08-01 17:08 shootingstars 阅读(197) | 评论 (0)编辑

五:regex_search学习
regex_search与regex_match基本相同,只不过regex_search不要求全部匹配,即部份匹配(查找)即可。
简单例子:
std::string regstr = "(\\d+)";
boost::regex expression(regstr);
std::
string testString = "192.168.4.1";
boost::smatch what;
if( boost::regex_search(testString, expression) )
{
    std::cout
<< "Have digit" << std::endl; 
}
上面这个例子检测给出的字符串中是否包含数字。

好了,再来一个例子,用于打印出所有的数字
std::string regstr = "(\\d+)";
boost::regex expression(regstr);
std::
string testString = "192.168.4.1";
boost::smatch what;
std::
string::const_iterator start = testString.begin();
std::
string::const_iterator end = testString.end();
while( boost::regex_search(start, end, what, expression) )
{
    std::cout
<< "Have digit:" ; 
    std::
string msg(what[1].first, what[1].second);
    std::cout
<< msg.c_str() << std::endl;
    start 
= what[0].second;
}
打印出:
Have digit:192
Have digit:168
Have digit:4
Have digit:1

posted @ 2007-08-01 15:12 shootingstars 阅读(247) | 评论 (0)编辑

四:regex_match例子代码学习
1 我们经常会看一个字符串是不是合法的IP地址,合法的IP地址需要符合以下这个特征:
  xxx.xxx.xxx.xxx 其中xxx是不超过255的整数
正则表达式找到上面的这种形式的字符串相当容易,只是判断xxx是否超过255就比较困难了(因为正则表达式是处理的文本,而非数字)
OK,我们先来处理一个数字,即:xxx。找到一种表达式来处理这个数字,并且保证这个数字不会超过255
第一种情况:x,即只有一个数字,它可以是0~9 ,用\d 表示
第二种情况:xx,即有两个数字,它可以是00~99,用\d\d 表示
第三种情况:xxx,这种情况分为两种,一种是 1xx,可以用 1\d\d 表示
                                   另外一种是 2xx,这又分为两种 2[1234]\d
                                                             和 25[12345]
好了组合起来
1?\d{1,2}|2[1234]\d|25[12345]
既可以标识一个不大于255的数字字符串

嗯,我们现在需要重复这种情况既可:
(1?\d{1,2}|2[1234]\d|25[12345])\.(1?\d{1,2}|2[1234]\d|25[12345])\.(1?\d{1,2}|2[1234]\d|25[12345])\.(1?\d{1,2}|2[1234]\d|25[12345])

呵呵,长是长了点,我试图用boost支持的子表达式缩短,但是没有达到效果,请各位了解boost的正则表达式的达人指点:
(1?\d{1,2}|2[1234]\d|25[12345])\.\1$\.\1$\.\1$
(参看反向索引:http://www.boost.org/libs/regex/doc/syntax_perl.html
似乎反向只能匹配与第一个字符完全一样的字符串,与我们的需求不同)

Example:
std::string regstr = "(1?\\d{1,2}|2[1234]\\d|25[12345])\\.(1?\\d{1,2}|2[1234]\\d|25[12345])\\.(1?\\d{1,2}|2[1234]\\d|25[12345])\\.(1?\\d{1,2}|2[1234]\\d|25[12345])";
boost::regex expression(regstr);
std::
string testString = "192.168.4.1";
if( boost::regex_match(testString, expression) )
{
    std::cout
<< "This is ip address" << std::endl;
}
else
{
    std::cout
<< "This is not ip address" << std::endl;
}

2 我们来看看regex_match的另外一个函数原型
template <class ST, class SA, class Allocator, class charT, class traits>
    bool regex_match(const basic_string<charT, ST, SA>& s,
    match_results<typename basic_string<charT, ST, SA>::const_iterator, Allocator>& m,
    const basic_regex <charT, traits>& e, match_flag_type flags = match_default);

template <class BidirectionalIterator, class Allocator, class charT, class traits>
bool regex_match(BidirectionalIterator first, BidirectionalIterator last,
match_results<BidirectionalIterator, Allocator>& m,
const basic_regex <charT, traits>& e,
match_flag_type flags = match_default);
 
注意参数m,如果这个函数返回false的话,m无定义。如果返回true的话,m的定义如下

Element

Value

m.size()

e.mark_count()

m.empty()

false

m.prefix().first

first

m.prefix().last

first

m.prefix().matched

false

m.suffix().first

last

m.suffix().last

last

m.suffix().matched

false

m[0].first

first

m[0].second

last

m[0].matched

true if a full match was found, and false if it was a partial match (found as a result of the match_partial flag being set).

m[n].first

For all integers n < m.size(), the start of the sequence that matched sub-expression n. Alternatively, if sub-expression n did not participate in the match, then last.

m[n].second

For all integers n < m.size(), the end of the sequence that matched sub-expression n. Alternatively, if sub-expression n did not participate in the match, then last.

m[n].matched

For all integers n < m.size(), true if sub-expression n participated in the match, false otherwise.

Example:
std::string regstr = "(1?\\d{1,2}|2[1234]\\d|25[12345])\\.(1?\\d{1,2}|2[1234]\\d|25[12345])\\.(1?\\d{1,2}|2[1234]\\d|25[12345])\\.(1?\\d{1,2}|2[1234]\\d|25[12345])";
boost::regex expression(regstr);
std::
string testString = "192.168.4.1";
boost::smatch what;
if( boost::regex_match(testString, what, expression) )
{
    std::cout
<< "This is ip address" << std::endl;
    
for(int i = 1;i <= 4;i++)
    {
        std::
string msg(what[i].first, what[i].second);
        std::cout
<< i << "" << msg.c_str() << std::endl;
    }
}
else
{
    std::cout
<< "This is not ip address" << std::endl;
}
这个例子会把所有的IP的单个数字答应出来:
This is ip address
1:192
2:168
3:4
4:1
posted @ 2007-08-01 11:23 shootingstars 阅读(266) | 评论 (0)编辑

2007年7月31日 #

近日在HBO看了前年斯皮尔伯格导的《世界大战》,上星期又去电影院看了《变形金刚》。
两部大片都是外星人在地球的故事。《世界大战》特效还是不错的,外星机器人在地球大开杀戒,毁灭了N个城市。只是结局似乎稍有点搞笑,外星人因为吃了地球上的东西,消化不良,被细菌给弄死了。而《变形金刚》则承载着我们对小时候的回忆:当听到“汽车人,变形,出发时”有点恍如隔世。

我这里倒不是想对两部大片提出什么看法,只是我对于目前我们人类理解的外星生命的范畴有些疑问:
一:外星生物必须是人类理解的生命吗?
    比如说必须有水,才能够有生命。(美国一直想弄清楚火星上有没有水,用以推断火星生命是否有存在的可能)。
    为什么不能有其他形式的生命存在呢?比如说机器人。我们目前发展计算机技术仅仅几十年时间,当然说人工智能目前还很稚嫩,但是再过几十年呢?或者再过几百年呢?

二:我们是否有必要去花费那么大的精力去寻求外星生命
    我是坚信外星生命是存在的,但是目前我们有没有必要去寻找外星生命?
    首先:上面提到的,外星生命不一定以我们所知道的形式存在。
    其次:沟通上,我们一般采用无线电方式向外太空发射信号,希望外星生命能够接收到,并且反馈。但是,无线电方式被地球人发现仅仅几百年时间,外星如果有生命(并且有文明)的话,他们是否会走地球人的路,或者走过地球人路,但是这种联系方式已经被淘汰掉了?(几百年的文明对于宇宙时间而言,太过短暂)
    再次:即使有外星生命(文明)存在的话,他们基本不可能跟地球文明在一个档次上。他们即使能够发现我们,但是他们不太可能会帮助我们(不在一个级别上),因此,也不会搭理我们。

    最后,对于火星人感到恐怖的人大可不必(原来有一个讲火星人入侵地球的故事,引起了欧洲一个国家的大骚动)。因为,如果外星文明有,而且能够到达地球,那么文明程度已经相当高了,完全没有必要用血腥的手段来灭绝一个星球。
posted @ 2007-07-31 14:33 shootingstars 阅读(99) | 评论 (1)编辑