周星星 之 Blog

关注 ASM/C/C++

  VC知识库BLOG :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 登录 ::
  127 随笔 :: 25 文章 :: 2609 评论 :: 9 Trackbacks
<2008年12月>
30123456
78910111213
14151617181920
21222324252627
28293031123
45678910

News

留言簿(45)

随笔分类

随笔档案

文章分类

文章档案

相册

相关链接

搜索

最新评论

  • 1. from hpho:
  • --周星星
  • 2. re: 目录监测(windows)
  • 非常感谢!但是有一个问题:就是我如何在一个线程中同步的监控多个文件夹?我不想使用太多线程……
  • --quantity
  • 3. re: 使用_alloca的一个Demo
  • 嗯,如果“这项技术非常适合这个需求”的话,那么与
    Test t1;
    t1.print();
    这样相比,它有什么优势呢?
  • --nosound
  • 4. re: 【暂存】不合理,但VC8能编译通过的代码
  • --wuqing
  • 5. 存照,待4年后看此两女大脑是不是还不正常
  • --周星星
  • 6. re: VS&G++ 重载operator delete的bug
  • --scu319hy
  • 7. 自创
  • 中国人的习惯是吃完了饭再付帐;洋人的习惯是先付帐后吃饭。
    于是餐馆老板想出了一个办法:
        与国际接轨:吃饭前先把饭钱付了;
        适应中国国情:吃完饭后付一次帐。
    这样一顿饭就可以收两次钱了。
  • --周星星
  • 8. re: windows下最好的C++ IDE
  • # re: windows下最好的C++ IDE 2008-05-18 14:58 xuebuyu 
    我试了最简单的程序,譬如只有一个std::cout << ..., printf (...), 发现vc2005产生的debug版本不能在没有.net framework下运行,而release可以
    ---------------------------------------------------------------------------
    debug版本也不需要的,可能是因为manifest文件的问题
  • --joe
  • 9. re: VS2005/VS2008 中64位数据引起的一个严重bug
  •  将 *(__int64*)(str+1) = *(__int64*)(str+0); 分解为
    *(__int32*)(str+5) = *(__int32*)(str+4);
    *(__int32*)(str+1) = *(__int32*)(str+0);
    就OK了

    看来关于__int64的赋值,编译的代码要根据两个变量地址来决定分解为两个__int32的操作的顺序
  • --mslk
  • 10. re: 网摘
  • 可惜中国人但对于羊显凶兽相,而对于凶兽则显羊相,所以即使显着凶兽相,也还是卑怯的国民。这样下去,一定要完结的。
    --- 《鲁迅警世名言录》
  • --周星星
  • 11. re: windows下最好的C++ IDE
  • 我在VC6.0里装了ICC,能正常使用.之前类模板的局部特化现在能编译通过了.但是在类声明里对静态数据成员初始化还是编译不过啊??
  • --keke
  • 12. re: 网摘
  • --周星星
  • 13. 自创
  • 两兄弟A和B,特穷,大哥A每次都忍饥挨饿却把B喂饱。
    长大后A瘦得像根杆,风一吹就倒;B却发育得很好,连吹3天牛屄也不累。

    B:A那家伙就是基因不好,人品不好,好吃懒做……,所以我现在身强力壮,他却赢弱得很,满身是病,快挂了。拖我家后腿呀!
    A:如果不是当年我把吃的留给你,你小子能油光满面,脑满肠肥,而我能在发育期间饿得营养不良,现在快挂了吗?
    B:当年我吃了你多少,现在我10倍还给你,看你能不能变得和我一样强壮?
    A:<气死了>
  • --周星星
  • 14. 杨辉三角(随便写的,估计有更好的写法)
  • --周星星
  • 15. to allenm:
  • 谢谢大虾。

    “为什么用wubi安装而不是直接硬盘安装呢?”
    ------ 一来需要分区,有些麻烦;二来8.10有bug,硬盘安装时无法分区,google了一下,可行的方法有:
    a. 用光盘安装
    b. 把启动文件放另一块硬盘,或U盘上。(a的原理其实和这个一样)
    c. 到分区时,先反挂载ISO所在分区
  • --周星星
  • 16. re: ubuntu8.10安装记
  • 囧,刚才没有看完你的文章就发评论了,现在发现很多我说的你已经解决了,另外说明一下你貌似还没有解决的上GTALK和MSN的问题吧,用系统自带的pidgin就可以了,这两个都可以上的,另外QQ也可以上,如果不可以上的话你可以去腾讯官网下载DEB包。
  • --allenm
  • 17. re: ubuntu8.10安装记
  • 你是刚开始用Ubuntu吧,其实这个很好用的,只是刚开始的时候你还不太适应罢了,为什么用wubi安装而不是直接硬盘安装呢?可以装个双系统啊,而且Ubuntu带的grub会直接找到你的windows分区,启动的时候可以选择。因为cd盘容量比较小,所以带的简体中文语言实际上是不完全的,你现在也打不出中文吧,你可以在系统设置里面找到语言设置选项,选择简体中文,然后会提示你安装语言包,用系统自带的新力得更新工具就可以了。更新完后设置一下SCIM输入法就可以打出中文了。另外国内的比较好的源有cn99,这个据说速度比较快
  • --allenm
  • 18. Wicd
  • http://www.lirui.name/post/134.html
  • --周星星
  • 19. re: ubuntu8.10安装记
  • 阿帮兔的口碑还不错滴。
    只是安装后敲入gcc你会很失望。。。。
  • --HateMath
  • 20. re: ubuntu8.10安装记
  • 根据 http://tech.ddvip.com/2008-06/121290441645303.html 制得后的对比

  • --周星星
  • 21. re longinus:
  • 谢谢,现在终于成功了,不知不觉间我牙齿都咬出血了:)
  • --周星星
  • 22. re: ubuntu8.10安装记
  • 分区的问题我一个朋友也遇到了,当时也没解决,可能是硬盘驱动的问题

    不过他后来装opensuse了……
  • --longinus
  • 23. Intel之CMOV等价指令
  • --周星星
  • 24. re: 暂存
  • --周星星
  • 25. re: windows下最好的C++ IDE
  • 个人感觉作为C++程序员不要太拘泥于工具,还是专注一下语言本身的东西,而且我根据自身的项目经验,发现很多企业都逐渐开始跨平台的开发,可见跨平台是大势所趋,所以对自身的发展还是专注对语言本身和各种跨平台标准库的学习和使用。
  • --Wing
  • 26. 顺便问问LZ一个相关的问题
  • 如果一段代码里执行了很多循环
    foo()
    {
       for(i=0;...){}
       for(i=0;...){}
       ...
     }
    这时那种代码更合理呢? 偶个人感觉适合把int i;定义到循环外似乎更好些,不知对否?
  • --假骑士
  • 27. re: 再次随便说说,缓解一下看到此代码所带来的郁闷
  • 代码二的好处是循环后,变量temp就可以消失了。
    重复定义的问题,其实循环内,temp一直存在,不存在重复定义的问题。
    另,实测了一下,这两段代码在VC++6里面的时间效率基本一致。
  • --假骑士
  • 28. re: 编译期时立即数溢出
  • --100000
  • 29. re: 实时数据库的简介(初稿)
  • 杨,你好:

       能不能告知 PI软件的价格体系。
  • --Xian
  • 30. re: 疑难
  • 怎么做可以为众生带来最大的利益?
  • --向月
  • 31. re: 编译期时立即数溢出
  • 老大,你的这些问题,都是怎么发现的啊,是会程序的bug中吗,觉得你真牛B
  • --ricardo
  • 32. re: [zdd]的一道题
  • --jjnet
  • 33. re: 再次随便说说,缓解一下看到此代码所带来的郁闷
  • 其实这根本就没有意义,只是个人风格不同而已,对此我既不反对也不赞同星星的说法.

    例子:我喜欢将花摆在门边外面(左面),老婆喜欢把花摆在门边里面(右面).一好事之人,非要对此指指点点,一笑而置之不理!
  • --非法用户
  • 34. re: 佛学佳句
  • 南无阿弥陀佛!  ^_^
  • --meiko
  • 35. re: windows下最好的C++ IDE
  • 各位有听说过C-Free吗?国人的作品。

    我觉得还是很不错的,它能够支持很多种编译器,VC或者GCC等都可以。目前最新好像是4.0版.
  • --allen
  • 36. re jeffer:
  • :)避开VC的bug是一回事,VC有没有这个bug是另一回事。
  • --周星星
  • 37. re Dark:
  • your are right, thanks
  • --周星星
  • 38. re: VS2005/VS2008 中编译流程的一个严重bug
  • 试了一下,DEBUG方式编译是错了,但是Release编译倒是正确的
  • --Dark
  • 39. re: **
  • --jeffer
  • 40. re jeffer:
  • 每个人第一眼看到这代码自然会如你这样想,我一开始也认为是“未定义”行为。
    不过仔细对比一下,*(__int64*)(str+0) 对operator= 而言是个值,因此根本不存在所谓的重叠。

    如果不想被*(__int64*)(str+0)迷住了眼,那么写成
    __int64 tmp = *(__int64*)(str+0);
    *(__int64*)(str+1) = tmp;
    在VS200X的release下同样输出错误数据。
  • --周星星
  • 41. re: VS2005/VS2008 中64位数据引起的一个严重bug
  • 精典的搬石頭砸到自己 , 當來源和目標重叠.
    不能稱為bug, 這算是 沒定義, 寫碼自己要避免
    就好比
       memcpy( src , src+4 , 5);
       memcpy( src+4 , src , 5);
  • --jeffer
  • 42. 给ms发一个bug report吧
  • rt
  • --局部变量
  • 43. 求M数中取N数的排列组合
  • --周星星
  • 44. re: 计算24点的小程序(更新版)
  • 您好,我想请问一下24点的算法原理。是否能详细讲解一下,谢谢!
  • --妮妮
  • 45. re: 网摘
  • 1956年12月18日,国务院曾发出《关于今后在行文中和书报杂志里一律不用“满清”的称谓的通知》。通知原文如下:

    “满清”这个名词是在清朝末年中国人民反对当时封建统治者这一段历史遗留下来的称谓。在目前我国各民族已经团结成为一个自由平等的民族大家庭的情况下,如果继续使用,可能使满族人民在情绪上引起不愉快的感觉。为了增进各民族间的团结,今后各级国家机关、学校、企业,各民主党派,各人民团体,在各种文件、著作和报纸、刊物中,除了引用历史文献不便改动外,一律不要用“满清”这个名称。(见1986年南京大学出版社出版的《统一战线工作手册》)
  • --周星星
  • 46. re: gcc/mingw/libstdc简介
  • 非常之谢谢。。。
  • --以函
  • 47. szj 求助GDI+
  • Image image( L"D:\\boy3.jpg" );
    参数用CString strFilePath来代替怎么写
  • --szj
  • 48. re: [zdd]的一道题
  • 我觉得并不是return造成的。return的时候有一个析构是正常的。多出来的析构是在参数传递的时候多出来的。
    我猜想,没有copy constructor的时候

    foo(A()) 等价于 A a; foo(a);
  • --Justin Shen
  • 49. re: 取浮点数的整数部分(确实有点无聊,不喜欢就召回删除)
  • double a = 6.7f;
    double b = a * 10;
    int c = a * 10;
    int d = b;

    printf( "%d", c ); // 输出 67
    printf( "%d", d ); // 输出 66

    如果是double的刚好相反也。
  • --re: 取浮点数的整数部分
  • 50. re: 实时数据库的简介(初稿)
  • 谁有WPKS安装说明?
  • --YangJun
  • 51. 这鸡蛋真难吃
  • --周星星
  • 52. re: VS2005/VS2008 的一个严重bug
  • defined _CHAR_UNSIGNED
    255
    0
    char_max = 255
    char_min = 0

    为什么我的 VS2008 没有?

  • --Orez
  • 53. re: VS2005/VS2008 的一个严重bug
  • 但愿微软加油了
  • --REgicide
  • 54. re: VS2005/VS2008 的一个严重bug
  • 哦,确实是MS的严重BUG
  • --100000
  • 55. re: VS2005/VS2008 的一个严重bug
  • 不会吧,这都能错
  • --gaoqing000
  • 56. re: time_t 和 DATE 之间的相互转化
  • --yqever
  • 57. re: time_t 和 DATE 之间的相互转化
  • 嘿嘿,多谢。
    收藏了。
  • --yqever
  • 58. 判断strtoull是否溢出,errno=0是必要的
  • --周星星
  • 59. re: VS2005/VS2008 的一个严重bug
  • defined _CHAR_UNSIGNED
    255
    0
    char_max = 127
    char_min = 128


    visual studio 2008 sp1 居然还是这样的.
  • --test
  • 60. re: VS&G++ 重载operator delete的bug
  • 当不同堆栈,delete 一个 void* 进不了 Destructor
    如果操作是在 堆A里 new ,到堆 B 里 delete。
    那么 
    void operator delete( void* raw )
    。。。
    delete( (foo*)raw ); 
    delete( (int*)raw );   或者
    delete( (typename T*)raw );  模板 
  • --布伦特

阅读排行榜

评论排行榜

专门保存代码片断

posted on 2007-04-19 11:21 周星星 阅读(7689) 评论(35)  编辑 收藏

评论

# re: temp 2007-04-19 15:35 周星星

  一个人在沙漠里快要饿死了,这时他捡到了神灯。
  神灯:“我只可以实现你一个愿望,快说吧,我赶时间。”
  人:“我要老婆……”
  神灯立刻变出一个美女,然后不屑的说:“都快饿死了还贪图美色!可悲!”说完就消失了。
  人:“……饼。”


  某日,龟爸、龟妈及龟儿子一家决定去郊游,他们带了一个山东大饼和两罐海底鸡,便出发到阳明山去了。苦爬十年,终于到了!他们席地而坐,卸下装备准备吃饭。
  结果,却发现没带开罐器!
  龟儿子:「……那我回去拿好了。」
  龟 爸:「乖儿子!快!爸妈等你回来一起开饭,快去快回ㄛ!」
  龟儿子:「一定要等我回来!不可食言喔!」
  于是龟儿子踏上归途………
  光阴似箭,岁月如梭,转眼间已过了20年,龟儿子却尚未出现。
  龟 妈:「老伴……要先开饭不?我超饿说……」
  龟 爸:「不行!我们答应儿子的!嗯……再等他五年,不来就不管他了!」
  转眼就是五年,龟儿子仍未见踪迹。龟龟爸妈不管了!二老决定开动。 拿出大饼正准备开吃……
  突然,龟儿子从树后探出头来……
  龟儿子:「靠!我就知道你们会偷吃!骗我回去拿开罐器?我等了二十五年,终于被我等到了吧!我最恨人家骗我了!」

某天三兄弟在公园里散步时看见路中间有件东西 "看起来像便便!" 大哥说, "我最好检查一下." 他弯下深吸了一口气, "闻起来像便便!" 他说  二哥走上前去把手指插进去感觉, "摸起来像便便." 他说  小弟戳了一下放进嘴里然後说, "尝起来也像便便 " 三兄弟终於松了口气说, "幸好我们没有踩到它!"

# [zt] C++中如何将一个数字三位三位加逗号?比如 1389992 输出为 1,389,992 2007-05-10 09:34 周星星

bruceteen的方法(使用一个如此设置的local):
#include <iostream>
#include <locale>

int main( void )
{
    using namespace std;

    cout << 1389992 << endl; // 1389992

    locale chs( "chs" ); // chs在我这里行,不知道你那里怎么样
    cout.imbue( chs );
    cout << 1389992 << endl; // 1,389,992
}

特别推荐 namtso的方法(自己订制local):
#include <iostream>
#include <string>
#include <locale>
using namespace std;

class thousands_sep_facet:public std::numpunct<char>
{
public:
    explicit thousands_sep_facet( size_t r=0 ) : std::numpunct<char>(r)
    {
    }
protected:
    string do_grouping() const
    {
        return "\003";
    }
};

int main( void )
{
    cout << 1389992 << endl; // 1389992

    locale loc( locale(), new thousands_sep_facet );
    std::cout.imbue( loc );
    cout << 1389992 << endl; // 1,389,992

    return 0;
}



# 传递可变参数列表 2007-08-29 11:59 周星星

#include <iostream>
using namespace std;

static void* funaddr_;
static void* retaddr_;
static int retvalue_;
__declspec(naked) int a( const char* _Format, ... )
{
    cout << "[Begin]" << endl;

    funaddr_ = &printf;
    __asm
    {
        pop retaddr_
        call funaddr_
        mov retvalue_, eax
        push retaddr_
    }

    cout << "[End]" << endl;

    __asm
    {
        mov eax, retvalue_;
        ret
    }
}

int main( void )
{
    int n = a( "%d\n", 123 );
    cout << n << endl;

    return 0;
}



# 给 游辉敏: 2007-09-18 10:22 周星星

http://www.vckbase.com/bbs/viewtopic.asp?id=3137365&pg=1

回复:
vckbase的消息有时不会弹出来,今天才看到你发的消息

1。inline只是一个“建议”,到底是否内联,是否不内联,完全取决于编译器。
2。inline在绝大部分情况下会提高运行时效率,但这不是绝对的,这取决于CPU。

3。为了测试,首先要解决第1个问题,VC++2005中使用__forceinline来强迫内联,使用__declspec(noinline)来强迫不内联

4。内联产生的效率提升是很小的,必须使用高精密的计时器,clock肯定不行^_^

5。还需要考虑编译器的代码优化,检验方法就是查看生成的汇编代码,看看是否真的内联了,是否真的未内联

6。现在的CPU运行时预测会影响到运行效率,所以待测试的代码必须先进行一次试运行,而后才能分辨运行效率

-------------------------
以下是我的测试代码,在我的CPU上能够明显看得出效率差别:
测试环境:VC++2005(SP1)、CPU PM 2.00Ghz

#include <windows.h>
#include <stdio.h>
class showtime_
{
public:
    showtime_()
    {
        QueryPerformanceFrequency( (LARGE_INTEGER*)&frequency_ );
        QueryPerformanceCounter( (LARGE_INTEGER*)&time1_ );
        GetThreadTimes( GetCurrentThread(), (LPFILETIME)&ftCreationTime1_, (LPFILETIME)&ftExitTime1_, (LPFILETIME)&ftKernelTime1_, (LPFILETIME)&ftUserTime1_ );
    }
    ~showtime_()
    {
        QueryPerformanceCounter( (LARGE_INTEGER*)&time2_ );
        GetThreadTimes( GetCurrentThread(), (LPFILETIME)&ftCreationTime2_, (LPFILETIME)&ftExitTime2_, (LPFILETIME)&ftKernelTime2_, (LPFILETIME)&ftUserTime2_ );
        printf( "PerformanceCounter: %lf\n", (time2_-time1_)*1.0/frequency_ );
        printf( "Kernel: %llu.%07llu; User: %llu.%07llu; Total: %llu.%07llu\n\n"
            , (ftKernelTime2_-ftKernelTime1_)/10000000, (ftKernelTime2_-ftKernelTime1_)%10000000
            , (ftUserTime2_-ftUserTime1_)/10000000, (ftUserTime2_-ftUserTime1_)%10000000
            , (ftKernelTime2_-ftKernelTime1_+ftUserTime2_-ftUserTime1_)/10000000, (ftKernelTime2_-ftKernelTime1_+ftUserTime2_-ftUserTime1_)%10000000 );
    }
private:
    unsigned long long frequency_, time1_, time2_;
    unsigned long long ftCreationTime1_,ftExitTime1_,ftCreationTime2_,ftExitTime2_;
    unsigned long long ftKernelTime1_,ftUserTime1_,ftKernelTime2_,ftUserTime2_;
};
#define showfollowtime showtime_ _;


struct foo1
{
    foo1() : value(0) {}

    __forceinline void bar() // 强制内联
    {
        ++value;
    }
   
    int value;
};

struct foo2
{
    foo2() : value(0) {}

    void bar();
   
    int value;
};
__declspec(noinline) void foo2::bar() // 强制不内联
{
    ++value;
}

int main( void )
{
    // 试运行,见6
    {
        foo1 a;
        for(int i = 0; i < 10000000; i++)
        {
            a.bar();
        }
        printf( "%d\n", a.value ); // 防止编译器优化直接给出a.value的数值,而不是运行时计算。下同
    }
    {
        foo2 a;
        for(int i = 0; i < 10000000; i++)
        {
            a.bar();
        }
        printf( "%d\n\n", a.value );
    }

    printf( "%s\n", "inline" );
    Sleep(0); // 消除剩余时间片,使得结果更准确。下同
    { showfollowtime

        foo1 a;
        for(int i = 0; i < 10000000; i++)
        {
            a.bar();
        }
        printf( "%d\n", a.value );
    }

    printf( "%s\n", "non-inline" );
    Sleep(0);
    { showfollowtime

        foo2 a;
        for(int i = 0; i < 10000000; i++)
        {
            a.bar();
        }
        printf( "%d\n", a.value );
    }

    printf( "%s\n", "non-inline" );
    Sleep(0);
    { showfollowtime

        foo2 a;
        for(int i = 0; i < 10000000; i++)
        {
            a.bar();
        }
        printf( "%d\n", a.value );
    }

    printf( "%s\n", "inline" );
    Sleep(0);
    { showfollowtime

        foo1 a;
        for(int i = 0; i < 10000000; i++)
        {
            a.bar();
        }
        printf( "%d\n", a.value );
    }
}



# 给 [shuishi32]: 2007-09-28 18:27 周星星
#include <iostream>
using namespace std;

struct Base
{
    virtual bool equal( const Base& lhs ) const
    {
        cout << "Base" << endl;
        return typeid(*this)==typeid(lhs) && (true); // (true) is only a test
    }
    bool operator==( const Base& lhs ) const
    {
        return equal(lhs);
    }
};
struct CA : Base
{
    virtual bool equal( const Base& lhs ) const
    {
        cout << "CA" << endl;
        return typeid(*this)==typeid(lhs) && (true); // (true) is only a test
    }
    bool operator==( const CA& lhs ) const
    {
        return equal(lhs);
    }
};
struct CB : Base
{
    virtual bool equal( const Base& lhs ) const
    {
        cout << "CB" << endl;
        return typeid(*this)==typeid(lhs) && (true); // (true) is only a test
    }
    bool operator==( const CB& lhs ) const
    {
        return equal(lhs);
    }
};

int main( void )
{
    Base *p1 = new CA;
    Base *p2 = new CB;
    Base *p3 = new CA;

    cout << ( (*p1)==(*p2) ) << endl;
    cout << ( (*p1)==(*p3) ) << endl;

    return 0;
}


# 给 [hhyang]: 2007-09-29 21:05 周星星

#include <time.h>
#include <math.h>

bool lotus2time( double dtSrc, struct tm& tmDest )
{
    const long MIN_DATE = -657434L;
    const long MAX_DATE = 2958465L;
    const double HALF_SECOND = 1.0/172800.0;
    const long month_days[13] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365};

    if( dtSrc>MAX_DATE || dtSrc<MIN_DATE )
        return false;

    bool bLeap4 = true;
    double dblDate = dtSrc + ((dtSrc > 0.0) ? HALF_SECOND : -HALF_SECOND);
    long nDays = (long)dblDate;
    long nDaysAbsolute = (long)dblDate + 693959L;
    dblDate = fabs(dblDate);
    long nSecsInDay = (long)((dblDate - floor(dblDate)) * 86400.);
    tmDest.tm_wday = (int)((nDaysAbsolute - 1) % 7L);
    long n400Years = (long)(nDaysAbsolute / 146097L);
    nDaysAbsolute %= 146097L;
    long n400Century = (long)((nDaysAbsolute - 1) / 36524L);

    long n4Years;
    long n4Day;
    if (n400Century != 0)
    {
        nDaysAbsolute = (nDaysAbsolute - 1) % 36524L;
        n4Years = (long)((nDaysAbsolute + 1) / 1461L);
        if (n4Years != 0)
            n4Day = (long)((nDaysAbsolute + 1) % 1461L);
        else
        {
            bLeap4 = false;
            n4Day = (long)nDaysAbsolute;
        }
    }
    else
    {
        n4Years = (long)(nDaysAbsolute / 1461L);
        n4Day = (long)(nDaysAbsolute % 1461L);
    }

    long n4Yr;
    if (bLeap4)
    {
        n4Yr = (n4Day - 1) / 365;

        if (n4Yr != 0)
            n4Day = (n4Day - 1) % 365;
    }
    else
    {
        n4Yr = n4Day / 365;
        n4Day %= 365;
    }

    tmDest.tm_yday = (int)n4Day + 1;
    tmDest.tm_year = n400Years * 400 + n400Century * 100 + n4Years * 4 + n4Yr;

    if (n4Yr == 0 && bLeap4)
    {
        if (n4Day == 59)
        {
            tmDest.tm_mon = 2;
            tmDest.tm_mday = 29;
            goto DoTime;
        }

        if (n4Day >= 60)
            --n4Day;
    }

    ++n4Day;

    for (tmDest.tm_mon = (n4Day >> 5) + 1;
        n4Day > month_days[tmDest.tm_mon]; tmDest.tm_mon++);

    tmDest.tm_mday = (int)(n4Day - month_days[tmDest.tm_mon-1]);

DoTime:
    if (nSecsInDay == 0)
        tmDest.tm_hour = tmDest.tm_min = tmDest.tm_sec = 0;
    else
    {
        tmDest.tm_sec = (int)nSecsInDay % 60L;
        long nMinutesInDay = nSecsInDay / 60L;
        tmDest.tm_min = (int)nMinutesInDay % 60;
        tmDest.tm_hour = (int)nMinutesInDay / 60;
    }

    tmDest.tm_mon -= 1;
    tmDest.tm_year -= 1900;
    tmDest.tm_yday -= 1;
    tmDest.tm_isdst = 0;
    return true;
}

#include <stdio.h>
int main()
{
    struct tm t;
    lotus2time( 39354.849004629628, t );
   
    printf( "%04d-%02d-%02d %02d:%02d:%02d\n", t.tm_year+1900, t.tm_mon+1, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec );
    printf( "星期%d, 本年第%d天\n", t.tm_wday, t.tm_yday+1 );

    return 0;
}



# 控制台测试 2007-11-02 15:31 周星星


//#include <stdio.h>
//#include <conio.h>
//
//int main( )
//{
//    for( ; ; )
//    {
//        int n = _getch();
//        switch( n )
//        {
//        case 0x00:
//        case 0xE0:
//            printf( "%02X %02X\n", n, _getch() );
//            break;
//        default:
//            printf( "%02X\n", n );
//        }
//    }
//
//    return 0;
//}

#include <windows.h>
#include <stdio.h>

BOOL WINAPI csl_handler_routine( DWORD CtrlType )
{
    switch( CtrlType )
    {
    case CTRL_C_EVENT:
    case CTRL_BREAK_EVENT:
    case CTRL_CLOSE_EVENT:
    case CTRL_LOGOFF_EVENT:
    case CTRL_SHUTDOWN_EVENT:
        // release resource
        SetConsoleCtrlHandler( &csl_handler_routine, FALSE );
        break;
    }
    return FALSE;
}

HANDLE hOutput_ = ::GetStdHandle(STD_OUTPUT_HANDLE);
HANDLE hInput_ = ::GetStdHandle(STD_INPUT_HANDLE);
COORD dwSize = { 60, 16 };
SHORT baselinenum = 0;

BOOL SetCursorPosition( SHORT x, SHORT y )
{
    COORD cd = { x, y+baselinenum };
    return ::SetConsoleCursorPosition( hOutput_, cd );
}

BOOL EarseTail( void )
{
    CONSOLE_SCREEN_BUFFER_INFO info;
    BOOL f = ::GetConsoleScreenBufferInfo( hOutput_, &info );
    printf( "%*s", dwSize.X-info.dwCursorPosition.X, "" );
    return f;
}

BOOL SetTextAttrib( WORD wAttributes )
{
    return ::SetConsoleTextAttribute( hOutput_, wAttributes );
}

void ShowControlKeyState( DWORD dwControlKeyState )
{
    SetTextAttrib( FOREGROUND_BLUE|FOREGROUND_GREEN|FOREGROUND_RED );
    printf( "" ); EarseTail();
    printf( "CAPS LOCK  : %s", (dwControlKeyState&CAPSLOCK_ON       )?"ON":"OFF" ); EarseTail();
    printf( "Enhanced   : %s", (dwControlKeyState&ENHANCED_KEY      )?"ON":"OFF" ); EarseTail();
    printf( "ALT Left   : %s", (dwControlKeyState&LEFT_ALT_PRESSED  )?"ON":"OFF" ); EarseTail();
    printf( "CTL Left   : %s", (dwControlKeyState&LEFT_CTRL_PRESSED )?"ON":"OFF" ); EarseTail();
    printf( "NUM LOCK   : %s", (dwControlKeyState&NUMLOCK_ON        )?"ON":"OFF" ); EarseTail();
    printf( "ALT Right  : %s", (dwControlKeyState&RIGHT_ALT_PRESSED )?"ON":"OFF" ); EarseTail();
    printf( "CTL Right  : %s", (dwControlKeyState&RIGHT_CTRL_PRESSED)?"ON":"OFF" ); EarseTail();
    printf( "SCROLL LOCK: %s", (dwControlKeyState&SCROLLLOCK_ON     )?"ON":"OFF" ); EarseTail();
    printf( "Shift      : %s", (dwControlKeyState&SHIFT_PRESSED     )?"ON":"OFF" ); EarseTail();
}
void ShowMouseInfo( MOUSE_EVENT_RECORD& mer )
{
    SetTextAttrib( FOREGROUND_BLUE|FOREGROUND_GREEN/*|FOREGROUND_RED*/ | FOREGROUND_INTENSITY );
    printf( "MousePosition: %03hd, %03hd", mer.dwMousePosition.X, mer.dwMousePosition.Y );                                                                       EarseTail();
    printf( "ButtonState:   Left=%c Right=%c", (mer.dwButtonState&FROM_LEFT_1ST_BUTTON_PRESSED)?'T':'F', (mer.dwButtonState&RIGHTMOST_BUTTON_PRESSED)?'T':'F' ); EarseTail();
    printf( "EventFlags:    " );
    switch( mer.dwEventFlags )
    {
    case 0            : printf( "Pressed or Released" ); EarseTail(); break;
    case DOUBLE_CLICK : printf( "double click       " ); EarseTail(); break;
    case MOUSE_MOVED  : printf( "mouse moved        " ); EarseTail(); break;
    case MOUSE_WHEELED: printf( "mouse wheeled      " ); EarseTail(); break;
    }

    ShowControlKeyState( mer.dwControlKeyState );
}

void ShowKeyInfo( KEY_EVENT_RECORD& ker )
{
    SetTextAttrib( FOREGROUND_BLUE/*|FOREGROUND_GREEN*/|FOREGROUND_RED | FOREGROUND_INTENSITY );
    printf( "KeyDown:          %c , Repeat Count:     %d", ker.bKeyDown?'T':'F', ker.wRepeatCount );       EarseTail();
    printf( "VirtualKeyCode:   %02X, wVirtualScanCode: %02X", ker.wVirtualKeyCode, ker.wVirtualScanCode ); EarseTail();
    printf( "AsciiChar:        %c", ker.uChar.AsciiChar );                                                 EarseTail();

    ShowControlKeyState( ker.dwControlKeyState );
}

int main( )
{
    // quit ctrl
    SetConsoleCtrlHandler( &csl_handler_routine, TRUE );

    // set window title
    ::SetConsoleTitle( TEXT("Test") );

    // get begin line number
    CONSOLE_SCREEN_BUFFER_INFO sinfo;
    ::GetConsoleScreenBufferInfo( hOutput_, &sinfo );
    baselinenum = sinfo.dwCursorPosition.Y;

    // hide cursor
    CONSOLE_CURSOR_INFO cinfo;
    ::GetConsoleCursorInfo( hOutput_, &cinfo );
    cinfo.bVisible = FALSE;
    ::SetConsoleCursorInfo( hOutput_, &cinfo );

    // set window size
    SMALL_RECT winsize = { 0, 0, dwSize.X-1, dwSize.Y-1 };
    ::SetConsoleWindowInfo( hOutput_, TRUE, &winsize );
    ::SetConsoleScreenBufferSize( hOutput_, dwSize );

    // enable mouse & window
    DWORD mode;
    ::GetConsoleMode( hInput_, &mode );
    mode |= ( ENABLE_MOUSE_INPUT | ENABLE_WINDOW_INPUT );
    ::SetConsoleMode( hInput_, mode );

    // get mouse & key
    INPUT_RECORD ir;
    DWORD index = 1;
    for( DWORD n; ReadConsoleInput(hInput_,&ir,1,&n); ++index )
    {
        SetCursorPosition( 0, 0);
        printf( "%d", index ); EarseTail();

        switch( ir.EventType )
        {
        case MOUSE_EVENT:
            ShowMouseInfo( ir.Event.MouseEvent );
            break;
        case KEY_EVENT:
            ShowKeyInfo( ir.Event.KeyEvent );
            break;
        }
    }

    // release resource
    // restore console setting

    return 0;
}

 



# 重载operator new的一般形式 2008-01-22 10:15 周星星


// 非类成员形式的operator new的伪代码:
void* operator new( size_t size ) // 包括其他形式
{
    if( 0 == size )
        size = 1;

    while(1)
    {
        分配size字节内存;
        if(分配成功)
            return 指向内存的指针;

        new_handler globalhandler = set_new_handler(0);
        set_new_handler(globalhandler);

        if( globalhandler )
            (*globalhandler)();
        else
            throw std::bad_alloc();
    }
}
void operator delete( void* raw )
{
    if( 0 == raw )
        return;

    ...
}

// 特定类的operator new的伪代码
struct base
{
    ...
    static void* operator new( size_t size );
};
void* base::operator new( size_t size )
{
    if( sizeof(base) != size )
        return ::operator new(size);

    同上
}
void base::operator delete( void* raw )
{
    if( 0 == raw ) return;
    if( sizeof(base) != size )
    {
        ::operator delete(raw);
        return;
    }

    ...
}



# 获取鼠标所在位置的颜色值 2008-01-22 12:09 周星星


#include <stdio.h>
#include <assert.h>
#include <windows.h>

HANDLE hInput;
HANDLE hOutput;
CONSOLE_CURSOR_INFO cursor_info;
CONSOLE_SCREEN_BUFFER_INFO screen_info;
DWORD mode;

// 设置控制台
void Init( void )
{
    // 得到控制台输入输出句柄
    hInput  = ::GetStdHandle(STD_INPUT_HANDLE);
    hOutput = ::GetStdHandle(STD_OUTPUT_HANDLE);
    assert( hInput  != INVALID_HANDLE_VALUE );
    assert( hOutput != INVALID_HANDLE_VALUE );

    // 隐藏光标
    BOOL f = ::GetConsoleCursorInfo( hOutput, &cursor_info );
    assert( f );
    CONSOLE_CURSOR_INFO cursor_info_new = cursor_info;
    cursor_info_new.bVisible = FALSE;
    f = ::SetConsoleCursorInfo( hOutput, &cursor_info_new );
    assert( f );

    // 得到控制台输出银屏缓冲信息
    ::GetConsoleScreenBufferInfo( hOutput, &screen_info );

    // 允许鼠标输入
    f = ::GetConsoleMode( hInput, &mode );
    assert( f );
    f = ::SetConsoleMode( hInput, mode|ENABLE_MOUSE_INPUT );
    assert( f );
}

// 复原控制台
void restore( void )
{
    ::SetConsoleMode( hInput, mode );
    ::SetConsoleCursorInfo( hOutput, &cursor_info );
    COORD cd = { 0, screen_info.dwCursorPosition.Y+2 };
    ::SetConsoleCursorPosition( hOutput, cd );
}

// 用于处理ctrl+c方式的退出
BOOL WINAPI CTRL_C_Routine( DWORD dwCtrlType )
{
    if( dwCtrlType == CTRL_C_EVENT )
    {
        // 复原控制台各项属性
        restore();
        // 卸载CTRL+C处理函数
        ::SetConsoleCtrlHandler( &CTRL_C_Routine, FALSE );
    }

    return FALSE;
}

// 获取鼠标所在位置的点颜色
int main( void )
{
    // 初始化控制台各项属性
    Init();

    // 安装CTRL+C处理函数
    BOOL f = ::SetConsoleCtrlHandler( &CTRL_C_Routine, TRUE );
    assert( f );

    // 得到桌面DC
    HWND hwnd = ::GetDesktopWindow();
    HDC hdc = ::GetWindowDC( hwnd );
    assert( hdc != 0 );

    // 提示信息
    puts( "press ESC key to quit." );
    puts( "press mouse left key and move ..." );

    // 获得键盘及鼠标输入
    INPUT_RECORD ir;
    for( DWORD n; ReadConsoleInput(hInput,&ir,1,&n) && n==1; )
    {
        // 跳到第1行第0列
        COORD cd = { 0, screen_info.dwCursorPosition.Y+1 };
        f = ::SetConsoleCursorPosition( hOutput, cd );
        assert( f );

        if( ir.EventType == MOUSE_EVENT ) // 鼠标信息
        {
            if( ir.Event.MouseEvent.dwEventFlags == MOUSE_MOVED ) // 鼠标移动
            {
                if( ir.Event.MouseEvent.dwButtonState&FROM_LEFT_1ST_BUTTON_PRESSED ) // 鼠标左键按下
                {
                    // 得到鼠标位置(非控制台)
                    POINT pt;
                    f = ::GetCursorPos( &pt );
                    assert( f );
                    // 得到鼠标颜色
                    COLORREF rgb = ::GetPixel( hdc, pt.x, pt.y );
                    assert( rgb != CLR_INVALID );
                    // 输出信息
                    int num = printf( "POINT(%ld,%ld): RGB(%u,%u,%u)", pt.x, pt.y, GetRValue(rgb), GetGValue(rgb), GetBValue(rgb) );
                    // 擦除尾部残余
                    printf( "%*s", screen_info.dwSize.X-num, "" );
                }
                else
                {
                    // 提示信息
                    int num = printf( "%s", "press mouse left key and move ..." );
                    // 擦除尾部残余
                    printf( "%*s", screen_info.dwSize.X-num, "" );
                }
            }
        }
        else if( ir.EventType == KEY_EVENT ) // 键盘信息
        {
            if( ir.Event.KeyEvent.wVirtualKeyCode == 0x1B )
                break;
        }
    }

    // 复原控制台各项属性
    restore();
}



# 一个最简单的DLL例子: 2008-01-27 10:49 周星星

建一个win32 dll空的工程,加入如下两个文件
//a.cpp
extern "C" __declspec(dllexport) int __stdcall test( int a, int b )
{
    return a+b;
}

//a.def
LIBRARY a
EXPORTS
    test @1

然后编译联结就得到 a.dll。
附:
a. 用 depends.exe 可以查看其导出函数。
b. 如果是vc8,需要打开工程属性页 configuration properties->Linker->Input->Module Definition File输入a.def
c. 如果需要进程线程控制,加入如下函数
BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}



# 显示进程树 2008-02-02 15:37 周星星


#include <windows.h>
#include <tlhelp32.h>
#include <iostream>
#include <iomanip>
#include <list>
#pragma comment(lib, "psapi")

bool GetProcessList( std::list<PROCESSENTRY32>& pcslst )
{
    pcslst.clear();

    HANDLE hProcessSnap = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
    if( hProcessSnap != INVALID_HANDLE_VALUE )
    {
        PROCESSENTRY32 pe32 = {0};
        pe32.dwSize = sizeof(PROCESSENTRY32);
        if( Process32First(hProcessSnap,&pe32) )
        {
            do
            {
                pcslst.push_back( pe32 );
            }
            while( Process32Next(hProcessSnap,&pe32) );
            CloseHandle( hProcessSnap );
            return true;
        }
        CloseHandle( hProcessSnap );
    }
    return false;
}
void ShowProcessList( void )
{
    std::list<PROCESSENTRY32> pcslst;
    if( GetProcessList(pcslst) )
    {
        for( std::list<PROCESSENTRY32>::iterator itor=pcslst.begin(); itor!=pcslst.end(); ++itor )
        {
            std::cout << itor->th32ParentProcessID << " " << itor->th32ProcessID << " " << itor->szExeFile << '\n';
        }
    }
}
void ShowProcessTree( void )
{
    using namespace std;

    struct ShowSubProcessTree
    {
        void operator()( std::list<PROCESSENTRY32>& pcslst, PROCESSENTRY32& pe32, std::streamsize spacenum )
        {
            cout << setw(spacenum) << setfill(' ') << "";
            cout << pe32.th32ProcessID << ": " << pe32.szExeFile << '\n';

            for( std::list<PROCESSENTRY32>::iterator itor=pcslst.begin(); itor!=pcslst.end(); ++itor )
            {
                if( itor->th32ProcessID!=itor->th32ParentProcessID && itor->th32ParentProcessID==pe32.th32ProcessID )
                {
                    ShowSubProcessTree()( pcslst, *itor, spacenum+4 );
                }
    &nbs