Prayer's profileMy Own PrisonPhotosBlogLists Tools Help

Blog


    January 04

    一个有趣的Java编译问题

    下面程序的main方法中的第二行代码和注释中的两行代码表达的意思完全相同,注释中的两行代码不能通过编译(这很容易理解),而第二行(采用方法调用链)却可以顺利通过编译(这就很难理解了)。
    public class Test
    {
        public void func()
        {
             System.out.println("func");
       }
     
       public static void main(String args[]) throws Exception
       {
               Object obj = new Test();

               //下面这行可以成功编译  
               ((Test)obj).getClass().newInstance().func();

               //下面这两行无法通过编译
               /*Class c = ((Test)obj).getClass();
               c.newInstance().func(); */
       
     }

     

    因为Generic, 编译器可以在编译期获得类型信息所以可以编译这类代码。你将下面那两行改成

    Class<? extends Test> c = ((Test)obj).getClass();
    c.newInstance().func();

    应该就能通过编译了。

     

    在JDK 1.5中引入范型后,Object.getClass()方法的定义如下:
    public final Class<? extends Object> getClass()
    Returns the runtime class of an object. That Class object is the object that is locked by static synchronized methods of the represented class.

     

    Returns:
    The java.lang.Class object that represents the runtime class of the object. The result is of type Class<? extends X> where X is the erasure of the static type of the expression on which getClass is called.

    这说明((Test)obj).getClass()语句返回的对象类型为Class<? extends Test>,而Class<T>的newInstance()方法的定义如下:
    public T newInstance() throws InstantiationException,IllegalAccessException
    即对于编译器看来,Class<Test>的newInstance()方法的对象类型为Test,而((Test)obj).getClass()返回的为对象类型为Class<? extends Test>,所以,编译器认为((Test)obj).getClass().newInstance()返回的对象类型为Test。

    下面这两行代码之所以无法通过编译
               Class c = ((Test)obj).getClass();
               c.newInstance().func();
    是因为((Test)obj).getClass()返回的为对象类型为Class<? extends Test>,但是我们在第一行将结果强制转换成了Class,然后再去调用Class的newInstance方法,而不是去调用Class<Test>的newInstance方法,编译器当然不再认为Class的newInstance方法返回的对象为Test了。

    下面是可以编译通过的:
    Class c = ((Test)obj).getClass();
    ((Test)(c.newInstance())).func();

    我觉得,应该是:
    c是Class对象,c.newInstance()实例化的是一个Object,还需要强制转换才是Test,才能调用func

     

     

    January 03

    C语言测试:想成为嵌入式程序员应知道的0x10个基本问题

       C语言测试是招聘嵌入式系统程序员过程中必须而且有效的方法。这些年,我既参加也组织了许多这种测试,在这过程中我意识到这些测试能为带面试者和被面试者提供许多有用信息,此外,撇开面试的压力不谈,这种测试也是相当有趣的。
     从被面试者的角度来讲,你能了解许多关于出题者或监考者的情况。这个测试只是出题者为显示其对ANSI标准细节的知识而不是技术技巧而设计吗?这个愚蠢的问题吗?如要你答出某个字符的ASCII值。这些问题着重考察你的系统调用和内存分配策略方面的能力吗?这标志着出题者也许花时间在微机上而不上在嵌入式系统上。如果上述任何问题的答案是"是"的话,那么我知道我得认真考虑我是否应该去做这份工作。
     从面试者的角度来讲,一个测试也许能从多方面揭示应试者的素质:最基本的,你能了解应试者C语言的水平。不管怎么样,看一下这人如何回答他不会的问题也是满有趣。应试者是以好的直觉做出明智的选择,还是只是瞎蒙呢?当应试者在某个问题上卡住时是找借口呢,还是表现出对问题的真正的好奇心,把这看成学习的机会呢?我发现这些信息与他们的测试成绩一样有用。
     有了这些想法,我决定出一些真正针对嵌入式系统的考题,希望这些令人头痛的考题能给正在找工作的人一点帮住。这些问题都是我这些年实际碰到的。其中有些题很难,但它们应该都能给你一点启迪。
     这个测试适于不同水平的应试者,大多数初级水平的应试者的成绩会很差,经验丰富的程序员应该有很好的成绩。为了让你能自己决定某些问题的偏好,每个问题没有分配分数,如果选择这些考题为你所用,请自行按你的意思分配分数。
    预处理器(Preprocessor)
    1 . 用预处理指令#define 声明一个常数,用以表明1年中有多少秒(忽略闰年问题)
     #define SECONDS_PER_YEAR (60 * 60 * 24 * 365)UL
     
     我在这想看到几件事情:
    ; #define 语法的基本知识(例如:不能以分号结束,括号的使用,等等)
    ; 懂得预处理器将为你计算常数表达式的值,因此,直接写出你是如何计算一年中有多少秒而不是计算出实际的值,是更清晰而没有代价的。
    ; 意识到这个表达式将使一个16位机的整型数溢出-因此要用到长整型符号L,告诉编译器这个常数是的长整型数。
    ; 如果你在你的表达式中用到UL(表示无符号长整型),那么你有了一个好的起点。记住,第一印象很重要。
     2 . 写一个"标准"宏MIN ,这个宏输入两个参数并返回较小的一个。
    #define MIN(A,B) ((A) <= (B) ? (A) : (B))
    这个测试是为下面的目的而设的:
    ; 标识#define在宏中应用的基本知识。这是很重要的,因为直到嵌入(inline)操作符变为标准C的一部分,宏是方便产生嵌入代码的唯一方法,对于嵌入式系统来说,为了能达到要求的性能,嵌入代码经常是必须的方法。
    ; 三重条件操作符的知识。这个操作符存在C语言中的原因是它使得编译器能产生比if-then-else更优化的代码,了解这个用法是很重要的。
    ; 懂得在宏中小心地把参数用括号括起来
    ; 我也用这个问题开始讨论宏的副作用,例如:当你写下面的代码时会发生什么事?
    least = MIN(*p++, b);
    3. 预处理器标识#error的目的是什么?
     如果你不知道答案,请看参考文献1。这问题对区分一个正常的伙计和一个书呆子是很有用的。只有书呆子才会读C语言课本的附录去找出象这种问题的答案。当然如果你不是在找一个书呆子,那么应试者最好希望自己不要知道答案。
    死循环(Infinite loops)
    4. 嵌入式系统中经常要用到无限循环,你怎么样用C编写死循环呢?
     这个问题用几个解决方案。我首选的方案是:
    while(1)
    {
    ?}
    一些程序员更喜欢如下方案:
    for(;
    {
    ?}
    这个实现方式让我为难,因为这个语法没有确切表达到底怎么回事。如果一个应试者给出这个作为方案,我将用这个作为一个机会去探究他们这样做的基本原理。如果他们的基本答案是:"我被教着这样做,但从没有想到过为什么。"这会给我留下一个坏印象。
     第三个方案是用 goto
    Loop:
    ...
    goto Loop;
    应试者如给出上面的方案,这说明或者他是一个汇编语言程序员(这也许是好事)或者他是一个想进入新领域的BASIC/FORTRAN程序员。
    数据声明(Data declarations)
    5. 用变量a给出下面的定义
     a) 一个整型数(An integer)
     b)一个指向整型数的指针( A pointer to an integer)
     c)一个指向指针的的指针,它指向的指针是指向一个整型数( A pointer to a pointer to an intege)r
     d)一个有10个整型数的数组( An array of 10 integers)
     e) 一个有10个指针的数组,该指针是指向一个整型数的。(An array of 10 pointers to integers)
     f) 一个指向有10个整型数数组的指针( A pointer to an array of 10 integers)
     g) 一个指向函数的指针,该函数有一个整型参数并返回一个整型数(A pointer to a function that takes an integer as an argument and returns an integer)
     h)一个有10个指针的数组,该指针指向一个函数,该函数有一个整型参数并返回一个整型数( An array of ten pointers to functions that take an integer argument and return an integer )
    答案是:
     a) int a; // An integer
     b) int *a; // A pointer to an integer
     c) int **a; // A pointer to a pointer to an integer
     d) int a[10]; // An array of 10 integers
     e) int *a[10]; // An array of 10 pointers to integers
     f) int (*a)[10]; // A pointer to an array of 10 integers
     g) int (*a)(int); // A pointer to a function a that takes an integer argument and returns an integer
     h) int (*a[10])(int); // An array of 10 pointers to functions that take an integer argument and return an integer
    人们经常声称这里有几个问题是那种要翻一下书才能回答的问题,我同意这种说法。当我写这篇文章时,为了确定语法的正确性,我的确查了一下书。但是当我被面试的时候,我期望被问到这个问题(或者相近的问题)。因为在被面试的这段时间里,我确定我知道这个问题的答案。应试者如果不知道所有的答案(或至少大部分答案),那么也就没有为这次面试做准备,如果该面试者没有为这次面试做准备,那么他又能为什么出准备呢?
     Static
     6. 关键字static的作用是什么?
     这个简单的问题很少有人能回答完全。在C语言中,关键字static有三个明显的作用:
    ; 在函数体,一个被声明为静态的变量在这一函数被调用过程中维持其值不变。
    ; 在模块内(但在函数体外),一个被声明为静态的变量可以被模块内所用函数访问,但不能被模块外其它函数访问。它是一个本地的全局变量。
    ; 在模块内,一个被声明为静态的函数只可被这一模块内的其它函数调用。那就是,这个函数被限制在声明它的模块的本地范围内使用。
    大多数应试者能正确回答第一部分,一部分能正确回答第二部分,同是很少的人能懂得第三部分。这是一个应试者的严重的缺点,因为他显然不懂得本地化数据和代码范围的好处和重要性。
    Const
    7.关键字const有什么含意?
     我只要一听到被面试者说:"const意味着常数",我就知道我正在和一个业余者打交道。去年Dan Saks已经在他的文章里完全概括了const的所有用法,因此ESP(译者:Embedded Systems Programming)的每一位读者应该非常熟悉const能做什么和不能做什么.如果你从没有读到那篇文章,只要能说出const意味着"只读"就可以了。尽管这个答案不是完全的答案,但我接受它作为一个正确的答案。(如果你想知道更详细的答案,仔细读一下Saks的文章吧。)
     如果应试者能正确回答这个问题,我将问他一个附加的问题:
     下面的声明都是什么意思?
    const int a;
    int const a;
    const int *a;
    int * const a;
    int const * a const;
     
    /******/
     前两个的作用是一样,a是一个常整型数。第三个意味着a是一个指向常整型数的指针(也就是,整型数是不可修改的,但指针可以)。第四个意思a是一个指向整型数的常指针(也就是说,指针指向的整型数是可以修改的,但指针是不可修改的)。最后一个意味着a是一个指向常整型数的常指针(也就是说,指针指向的整型数是不可修改的,同时指针也是不可修改的)。如果应试者能正确回答这些问题,那么他就给我留下了一个好印象。顺带提一句,也许你可能会问,即使不用关键字 const,也还是能很容易写出功能正确的程序,那么我为什么还要如此看重关键字const呢?我也如下的几下理由:
    ; 关键字const的作用是为给读你代码的人传达非常有用的信息,实际上,声明一个参数为常量是为了告诉了用户这个参数的应用目的。如果你曾花很多时间清理其它人留下的垃圾,你就会很快学会感谢这点多余的信息。(当然,懂得用const的程序员很少会留下的垃圾让别人来清理的。)
    ; 通过给优化器一些附加的信息,使用关键字const也许能产生更紧凑的代码。
    ; 合理地使用关键字const可以使编译器很自然地保护那些不希望被改变的参数,防止其被无意的代码修改。简而言之,这样可以减少bug的出现。
     Volatile
    8. 关键字volatile有什么含意?并给出三个不同的例子。
     一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。下面是volatile变量的几个例子:
    ; 并行设备的硬件寄存器(如:状态寄存器)
    ; 一个中断服务子程序中会访问到的非自动变量(Non-automatic variables)
    ; 多线程应用中被几个任务共享的变量
    回答不出这个问题的人是不会被雇佣的。我认为这是区分C程序员和嵌入式系统程序员的最基本的问题。搞嵌入式的家伙们经常同硬件、中断、RTOS等等打交道,所有这些都要求用到volatile变量。不懂得volatile的内容将会带来灾难。
     假设被面试者正确地回答了这是问题(嗯,怀疑是否会是这样),我将稍微深究一下,看一下这家伙是不是直正懂得volatile完全的重要性。
    ; 一个参数既可以是const还可以是volatile吗?解释为什么。
    ; 一个指针可以是volatile 吗?解释为什么。
    ; 下面的函数有什么错误: int square(volatile int *ptr)
    {
    return *ptr * *ptr;
    }
    下面是答案:
    ; 是的。一个例子是只读的状态寄存器。它是volatile因为它可能被意想不到地改变。它是const因为程序不应该试图去修改它。
    ; 是的。尽管这并不很常见。一个例子是当一个中服务子程序修该一个指向一个buffer的指针时。
    ; 这段代码有点变态。这段代码的目的是用来返指针*ptr指向值的平方,但是,由于*ptr指向一个volatile型参数,编译器将产生类似下面的代码: int square(volatile int *ptr)
    {
    int a,b;
    a = *ptr;
    b = *ptr;
    return a * b;
    }
    由于*ptr的值可能被意想不到地该变,因此a和b可能是不同的。结果,这段代码可能返不是你所期望的平方值!正确的代码如下:
    long square(volatile int *ptr)
    {
    int a;
    a = *ptr;
    return a * a;
    }
    位操作(Bit manipulation)
    9. 嵌入式系统总是要用户对变量或寄存器进行位操作。给定一个整型变量a,写两段代码,第一个设置a的bit 3,第二个清除a 的bit 3。在以上两个操作中,要保持其它位不变。
     对这个问题有三种基本的反应
    ; 不知道如何下手。该被面者从没做过任何嵌入式系统的工作。
    ; 用bit fields。Bit fields是被扔到C语言死角的东西,它保证你的代码在不同编译器之间是不可移植的,同时也保证了的你的代码是不可重用的。我最近不幸看到 Infineon为其较复杂的通信芯片写的驱动程序,它用到了bit fields因此完全对我无用,因为我的编译器用其它的方式来实现bit fields的。从道德讲:永远不要让一个非嵌入式的家伙粘实际硬件的边。
    ; 用 #defines 和 bit masks 操作。这是一个有极高可移植性的方法,是应该被用到的方法。最佳的解决方案如下: #define BIT3 (0x1 << 3)
    static int a;
    void set_bit3(void) {
    a |= BIT3;
    }
    void clear_bit3(void) {
    a &= ~BIT3;
    }
     
    一些人喜欢为设置和清除值而定义一个掩码同时定义一些说明常数,这也是可以接受的。我希望看到几个要点:说明常数、|=和&=~操作。
    访问固定的内存位置(Accessing fixed memory locations)
     
    10. 嵌入式系统经常具有要求程序员去访问某特定的内存位置的特点。在某工程中,要求设置一绝对地址为0x67a9的整型变量的值为0xaa66。编译器是一个纯粹的ANSI编译器。写代码去完成这一任务。
     这一问题测试你是否知道为了访问一绝对地址把一个整型数强制转换(typecast)为一指针是合法的。这一问题的实现方式随着个人风格不同而不同。典型的类似代码如下:
    int *ptr;
    ptr = (int *)0x67a9;
    *ptr = 0xaa55;
    A more obscure approach is:
    一个较晦涩的方法是:
    *(int * const)(0x67a9) = 0xaa55;
     
    即使你的品味更接近第二种方案,但我建议你在面试时使用第一种方案。
    中断(Interrupts)
    11. 中断是嵌入式系统中重要的组成部分,这导致了很多编译开发商提供一种扩展—让标准C支持中断。具代表事实是,产生了一个新的关键字 __interrupt。下面的代码就使用了__interrupt关键字去定义了一个中断服务子程序(ISR),请评论一下这段代码的。
    __interrupt double compute_area (double radius)
    {
    double area = PI * radius * radius;
    printf("\nArea = %f", area);
    return area;
    }
    这个函数有太多的错误了,以至让人不知从何说起了:
    ; ISR 不能返回一个值。如果你不懂这个,那么你不会被雇用的。
    ; ISR 不能传递参数。如果你没有看到这一点,你被雇用的机会等同第一项。
    ; 在许多的处理器/编译器中,浮点一般都是不可重入的。有些处理器/编译器需要让额处的寄存器入栈,有些处理器/编译器就是不允许在ISR中做浮点运算。此外,ISR应该是短而有效率的,在ISR中做浮点运算是不明智的。
    ; 与第三点一脉相承,printf()经常有重入和性能上的问题。如果你丢掉了第三和第四点,我不会太为难你的。不用说,如果你能得到后两点,那么你的被雇用前景越来越光明了。
    *****
     代码例子(Code examples)
    12 . 下面的代码输出是什么,为什么?
    void foo(void)
    {
    unsigned int a = 6;
    int b = -20;
    (a+b > 6) ? puts("> 6") : puts("<= 6");
    }
    这个问题测试你是否懂得C语言中的整数自动转换原则,我发现有些开发者懂得极少这些东西。不管如何,这无符号整型问题的答案是输出是 ">6"。原因是当表达式中存在有符号类型和无符号类型时所有的操作数都自动转换为无符号类型。因此-20变成了一个非常大的正整数,所以该表达式计算出的结果大于6。这一点对于应当频繁用到无符号数据类型的嵌入式系统来说是丰常重要的。如果你答错了这个问题,你也就到了得不到这份工作的边缘。
     13. 评价下面的代码片断:
    unsigned int zero = 0;
    unsigned int compzero = 0xFFFF;
    /*1's complement of zero */
    对于一个int型不是16位的处理器为说,上面的代码是不正确的。应编写如下:
    unsigned int compzero = ~0;
    这一问题真正能揭露出应试者是否懂得处理器字长的重要性。在我的经验里,好的嵌入式程序员非常准确地明白硬件的细节和它的局限,然而PC机程序往往把硬件作为一个无法避免的烦恼。
     到了这个阶段,应试者或者完全垂头丧气了或者信心满满志在必得。如果显然应试者不是很好,那么这个测试就在这里结束了。但如果显然应试者做得不错,那么我就扔出下面的追加问题,这些问题是比较难的,我想仅仅非常优秀的应试者能做得不错。提出这些问题,我希望更多看到应试者应付问题的方法,而不是答案。不管如何,你就当是这个娱乐吧...
    动态内存分配(Dynamic memory allocation)
     14. 尽管不像非嵌入式计算机那么常见,嵌入式系统还是有从堆(heap)中动态分配内存的过程的。那么嵌入式系统中,动态分配内存可能发生的问题是什么?
     这里,我期望应试者能提到内存碎片,碎片收集的问题,变量的持行时间等等。这个主题已经在ESP杂志中被广泛地讨论过了(主要是 P.J. Plauger, 他的解释远远超过我这里能提到的任何解释),所有回过头看一下这些杂志吧!让应试者进入一种虚假的安全感觉后,我拿出这么一个小节目:
     下面的代码片段的输出是什么,为什么?
    char *ptr;
    if ((ptr = (char *)malloc(0)) ==
    NULL)
    else
    puts("Got a null pointer");
    puts("Got a valid pointer");
    这是一个有趣的问题。最近在我的一个同事不经意把0值传给了函数malloc,得到了一个合法的指针之后,我才想到这个问题。这就是上面的代码,该代码的输出是"Got a valid pointer"。我用这个来开始讨论这样的一问题,看看被面试者是否想到库例程这样做是正确。得到正确的答案固然重要,但解决问题的方法和你做决定的基本原理更重要些。
     
     Typedef
    :
     15 Typedef 在C语言中频繁用以声明一个已经存在的数据类型的同义字。也可以用预处理器做类似的事。例如,思考一下下面的例子:
    #define dPS struct s *
    typedef struct s * tPS;
    以上两种情况的意图都是要定义dPS 和 tPS 作为一个指向结构s指针。哪种方法更好呢?(如果有的话)为什么?
     这是一个非常微妙的问题,任何人答对这个问题(正当的原因)是应当被恭喜的。答案是:typedef更好。思考下面的例子:
    dPS p1,p2;
    tPS p3,p4;
    第一个扩展为
    struct s * p1, p2;
     
    上面的代码定义p1为一个指向结构的指,p2为一个实际的结构,这也许不是你想要的。第二个例子正确地定义了p3 和p4 两个指针。
    晦涩的语法
    16 . C语言同意一些令人震惊的结构,下面的结构是合法的吗,如果是它做些什么?
    int a = 5, b = 7, c;
    c = a+++b;
    这个问题将做为这个测验的一个愉快的结尾。不管你相不相信,上面的例子是完全合乎语法的。问题是编译器如何处理它?水平不高的编译作者实际上会争论这个问题,根据最处理原则,编译器应当能处理尽可能所有合法的用法。因此,上面的代码被处理成:
    c = a++ + b;
    因此, 这段代码持行后a = 6, b = 7, c = 12。
     如果你知道答案,或猜出正确答案,做得好。如果你不知道答案,我也不把这个当作问题。我发现这个问题的最大好处是这是一个关于代码编写风格,代码的可读性,代码的可修改性的好的话题。
     好了,伙计们,你现在已经做完所有的测试了。这就是我出的C语言测试题,我怀着愉快的心情写完它,希望你以同样的心情读完它。如果是认为这是一个好的测试,那么尽量都用到你的找工作的过程中去吧。天知道也许过个一两年,我就不做现在的工作,也需要找一个。
    November 02

    Math.....

     
          范函、欧拉-拉格朗日方程、变分法、黎曼空间、梯度、散度、有限元、差分、偏微分方程。。。。。。TMD我要晕了。。。。
    September 11

    软件开发和架构人员之必读经典书籍!

     
    1 设计模式:可复用面向对象软件的基础
       -Erich Gamma,Richard Helm,Ralph Johnson,John Vlissides
     
     
    2 企业应用架构模式   
       -Martin Fowler
     
     
    3 敏捷软件开发:原则、模式与实践
      -Robert C. Martin
     
     
    4 重构:改善既有代码的设计
       -Martin Fowler
     
     
    5 测试驱动开发——实用指南
       -Dave Astels
     
     
    6 UML与模式应用
       -Craig Larman
     
    7 Expert One-on-One J2EE Design and Development(中文版暴烂,千万不要买!!!)
       -Rod Johnson
     
     
    8 Expert One-on-One J2EE Development without EJB
       -Rod Johnson,Juergen Hoeller
     
     
    9 代码大全
       -Steve McConnell
     
    10 J2EE核心模式
       -Deepak Alur,John Crupi,Dan Malks
     

     

     

     
    August 04

    SUSE Enterprise 10!!!

        今天得到的一条重要消息是Novell发布了最新的Linux系统:SUSE Enterprise 10桌面版和服务器版。SUSE界面之华丽,功能之强大,恐怕没有其他的Linux版本可以相提并论!发布仅10天后下载次数就超过了165000次,并且SUSE Enterprise 10的网页有超过312000次点击,而Novell.com的软件下载量在SUSE 10发布后提高了800%!
        可怜我的硬盘,又要腾出空间了~~
    August 03

    3DS Max乎??? Maya乎????

        Maya 8在前不久发布了出来。令人感到惊奇的是,标题写的是 Autodesk Maya 8 ,而不是Alias Maya 8。上网查了一下,Alias已经被Autodesk收购了。这就让人奇怪了。Autodesk有他著名的3D制作软件3DS Max,如今兼并了Alias,吸收了三大3D制作软件中的另一个Maya,固然可以提高其在多媒体制作方面的整体地位,但是,Autodesk仍然保留Maya的研发团队,而不是并入3Ds Max的生产线,并且还推出了Maya 8,这就让人觉得奇怪了。Maya和3DS Max是绝对有直接的竞争关系的,不知道Autodesk此举是何意义。升至在Autodesk的主页上3DS Max和Maya的广告词都是一模一样。让市场上同时出现同公司的两种互相竞争的产品?有必要么?还是只是一个过渡阶段,想要挽留Maya的老客户???不过怎么看,Autodesk的市场战略都让人匪夷所思。
        不过可以肯定的是,此举肯定会对XSI和其他3D制作软件产生巨大的冲击。Autodesk下一步准备怎么走,拭目以待。
    July 21

    Symbian OS 2nd!!!

        今天装了CodeWarrior,一切正常,不过CW有使用期限,只能用15天,而破解程序又用不了。。
     
        下了一个Carbide C++。。Nokia的Carbide系列,居然每个程序都是不同类型的程序。Carbide J是以前的NDS,带有Nokia PC Suits,是一个包含手机模拟器、PC-手机连接程序、移动设备管理程序的综合软件包,包括一套J2ME库;Carbide VS是让S60 SDK能在VS下使用的VS插件,需要已经安装了S60 SDK才能安装使用;而Carbide C++就是一个改造了的Eclipse,不过是用C++来开发的。不过Carbide J安装后需要手动添加设备,而Carbide VS和Carbide C++都可以检测到机器里面已经安装了的Symbian OS SDK。
    July 20

    The Symbian OS~!!

        搞个手机开发比我以前想象的要麻烦多了。主要是手机软件平台更新速度太快,从Symbian 7.0,8.0到现在的9.0。从支持Symbian 8.0的S60 SDK fp3版本开始,SDK就不分Visual Studio、CodeWarrior和GCC版本了,也不再有对Visual Studio的直接支持。要在VS里面使用对应Symbian OS 9.0的S60 SDK第3版需要下载安装NDS。不过,Nokia从NDS3.0之后就不叫NDS了,而是叫Carbide:对应VS平台的叫做Carbide vs,对应J2ME平台的叫做Carbide j。。但是在S60 SDK第3版的帮助文件中依然称之为NDS。晕死。。。计算是下了NDS,也只能在VS2003下使用,而且新建项目的时候只能选择“Symbian OS 9.0”,不能使用“Classic”,而且因为SDK不直接支持VS,所以里面的示例文件是针对CodeWarrior的,不能在VS下使用也不能直接用命令行编译成VS可以识别的项目文件。于是我又不得不去下载一个S60 SDK 2 FP2的支持VS的版本,总算是可以在VS下面使用了,也可以使用命令行编译SDK自带的示例文件。不过这样也带来了一个问题,就是在不同的SDK之间切换,如何选择一个默认的SDK,上网看了一下,还没找到很好的方法,总之很麻烦。。。。
        现在我所有的关于Symbian OS和S60平台的书都是讲S60 SDK 2.0版本的。用了一下发觉3.0版本跟2.0相比有了很多改变,甚至连编译使用的MMP文件格式都不同了。看来只能暂时先学学2.0,等装好了CodeWarrior再试试3.0。不过OpengGL1.1插件只能在3.0的SDK中用,真是麻烦。。。
        不仅是S60的SDK,连最新的UIQ SDK也不再直接支持VS,开来微软在移动开发这一块已经逐渐开始被抛弃了。
    July 02

    SUSE Linux Professional 10.1 安装的一些问题事项

        首先在VMWare下面建了个10G虚拟机。将光驱设置为SUSE Linux的安装镜像。启动虚拟机,进入SUSE的安装界面。然后一路继续下去,直到“安装配置”。
        在“软件”一项下面显示:
        hd://suse?device%3d%2fdev%2fsda6%26filesystem%3dauto" 上未发现任何项目
        错误: 无建议
        上网搜索了一下,使用虚拟机安装的人不少都遇到了这个问题。
        解决方法:到“安装配置”环节时,选择“中断”,询问安装未完成是否继续选择“否”,退出安装环境,提示“安装出现错误”选择“确定”,然后出现一个选项,一路回车,最后重新进入安装程序。这次再到“安装配置”环节时没有出现前面出现的错误了。
     
        然后将硬盘分区。我为虚拟机分的硬盘空间是10G,因此将/home分区设置为6G。结果在选择安装的软件的时候,提示硬盘已满。天,默认安装要2.3G空间,完全安装需要7G的空间,真是庞大无比。。。。。。没办法,关闭虚拟机,删除虚拟机,重新创建一个虚拟机,分了15G的硬盘空间,重新安装SUSE,然后将/home分区设成>7G。。。。
     
        使用虚拟机的一个好处是可以随时暂停。因为要看球,所以把虚拟机暂停了,挂起了安装进程,下午继续~
     
     
        继续安装,又出现了问题:硬盘无法格式化。无论是将硬盘设置成IDE的还是串口的,把桌面设成KDE还是GNOME都不行。上网查了下,有人反应是VMware对DVD镜像支持不好。解决方法吗,使用虚拟光驱,而不是用VMware直接加载镜像。实践证明以前出现的错误也不再出现。
     
        明天准备继续搞定XGL 3D桌面。冲着3D桌面我才决定装SUSE的,不过今天看了下官方的英文教程,好像很麻烦。
     
     

    无法找到双系统启动菜单

        今天电脑遇到一点小问题。用金山杀毒的时候,遇到内存里面一个文件“h9vlcc.dll”时金山就会卡住。于是乎在系统里面找到了这个文件,发现无法直接删掉他,提示写保护。于是,我就用一个暴力删除软件将这个文件强行删除。这一下,重启系统出现了问题,双系统启动菜单变成了“Load from D:\Windows1\ 。。。。。”然后直接进入了xp系统(我系统时XP和2003 Server双系统。XP在C盘,2003在D盘)
        手头上没有2003 Server的安装盘,因此也无法通过用安装盘修复来重新回复双系统启动菜单。打开C盘发现双系统启动菜单需要的几个文件都没有了(其实以前也没有在意那几个文件是不是在)。
        后来抱着试一试的心理,在C盘里面搜索“boot”(boot.ini,双系统启动菜单的配置文件),忽然发现C:\Winows\pss 文件夹下有一个叫做“boot.ini.backup”的文件。不用说,这肯定时boot.ini的备份。于是,将其copy到C盘根目录下,然后改名为“boot.ini”,重启,双系统菜单终于回来了!!!
     
        不知道是不是因为除了这个文件还需要其他文件,启动菜单跟以前的不同,极其丑陋,但好在问题暂时解决了。。
     
        以下是“boot.ini”的内容:
     
    [boot loader]
    timeout=30
    default=multi(0)disk(0)rdisk(0)partition(2)\WINDOWS1
    [operating systems]
    multi(0)disk(0)rdisk(0)partition(2)\WINDOWS1="Windows Server 2003, Standard" /fastdetect
    multi(0)disk(0)rdisk(0)partition(1)\WINDOWS="Microsoft Windows XP Professional" /fastdetect
     
     
    June 15

    DirectX的AppWizard

        今天非常郁闷,装了最新版的Directx 9.0c sdk,结果发现该sdk是不带directx向导的。于是想卸载掉重新装回Directx 9.0a sdk。结果发现装好后却无法初始化DirectX AppWizzard生成的项目,提示项目设置出错。而Directx 9.0c sdk中自带的例子也是完全基于VS.net 2003和VS 2005的,无法直接在VS 6.0里面使用。
     
        后来发现,使用DirectX AppWizard向导生成程序框架的时候,并没有把相应的DirectX库函数加入到项目中。没办法,只好根据出错的信息以个个寻找相应的.lib文件。得到的所需库文件列表如下:
     
    comctl32.lib d3dx9d.lib dxguid.lib winmm.lib dxerr9.lib d3dxof.lib d3dx9.lib d3d9.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib
     
        特别是comctl32.lib文件,如果不加将会无法使用 InitCommonControls() 函数,出现错误:error   LNK2001:   unresolved   external   symbol   __imp__InitCommonControls@0
        而不加winmm.lib文件,则会无法使用 timeGetTime() 函数,出现错误:error LNK2001: unresolved external symbol __imp__timeGetTime@0
        以上两个库都不是DirectX的库。
     
        可以在项目->设置->链接里面加,也可以在程序里面使用下面语句动态添加:
       
        #pragma comment(lib, "comctl32")
     
        经过试验,9.0a(或9.0b)版跟9.0c版可以共存。如果先装9.0c版再装9.0b版,那么VS.net 2003将使用9.0c版的库文件和头文件,而VS 6.0将使用9.0b版的库文件和头文件,不过使用向导生成框架时会出现问题,需要加入上面列出的一些库文件。
     
        另:9.0c版本支持VS 2005,所有的例子都完全基于VS.net 2003和VS 2005。Samples文件夹里面还包含有DirectX 10的例子,不过我的机器无法编译通过。
     
         使用VS 6.0时,最好在“选项”的“目录”里面加入下面的原文件和头文件:
     
        F:\DXSDK\SAMPLES\C++\COMMON\INCLUDE
        F:\DXSDK\SAMPLES\C++\COMMON\SRC
    June 14

    DirectX的下载地址

    最新的DirectX 9.0c版本runtime和SDK的下载地址:
     
     
     
    Runtime增加了原版9.0c中几个缺少了的dll文件。
    SDK增加了将3DS文件转换成.x文件的工具。
    May 24

    【转贴】最真实的2006年应届毕业生真实薪水

      按行业划分
      
      [通讯]
      上海贝尔阿而卡特:8w/y 硕 (包括福利) (harry)
      朗讯青岛:7.5k/m 硕
      朗讯北京:9.6k/m 硕
      Cisco上海:9w/y 硕
      华为: 5000+800 硕士
      爱立信北京:6500税前
      西门子AD:3200
      中电赛龙 5050+800+150 硕士
      大唐移动 5500+900(车补房补饭补)
      大唐兴唐3650/m 硕士 (avivi)
      大唐信威研发 5500+900 硕士 (avivi)
      瑞斯康达 试用期5k,转正6k,补助有几百,硕士(avivi)
      中兴 5750 硕士 (avivi,lgb)
      数码视讯 4500-6000 硕士(avivi)
      阿德利亚 6k (avivi)
      港湾 4500+500 硕士 (avivi)
      
      
      [运营商]
      北京联通:硕士4000+2000/M
      太原联通:实习期3000/M本科
      上海联通:转正后10W/Y(加福利)
      河北联通:
      >试用期3-6个月 见习期1年 试用期在见习期内
      >试用期小本850
      >然后转正 定岗 见习期内奖金拿0.5
      >最低级的业务员是1到4岗 一般上来也只能定成1岗
      >1岗工资950 4岗工资1950
      >奖金占薪酬的50%
      >发13个月
      >剩下的就是补助 年终 逢年过节的发个钱了
      
      东莞电信:本本 实习期4W/Y,转正7~8W/Y(包括基本工资和奖金)
      广州电信:不具体说但是说平均每人9W.工资总额/人数.税后
      深圳电信:第一年6W.转正后9W.税后
      
      上海网通:转正后12W/Y (加福利)
      太原网通:1500-1600
      
      重庆移动:(CrewZ)
      >本本 实习期6个月 ,1k2/M
      >转正后7岗,2k+/M(平时所有的加在一起到手的,不算年终)
      
      
      [软件]
      微软:SDE14w/y SDET 12.5w/y
      腾讯:10w/y 硕 7w/y 本
      百度:研发13w/y 硕 业务类非常低
      Google:16k/m 硕
      盛大:本科4000,硕士5500.3个月的实习期.实习期待遇为正式的80%
      TOM网:本科4500税前
      汉略:本,3.2-3.5k税前+绩效奖金
      Infosys:
      >试用期6个月,培训10/18周(短期/长期,视是否为计算机、软件专业而定),其间
      >2.5k/m(本科)计算机、软件的为3k,转正另议。发13个月薪水,其中第13个月为全年
      >最高的一次工资。(deazi)
      
      
      [PC]
      明基:2500左右
      华硕:3000左右
      VIA:7000/m 提供宿舍 硕士 4000/m 本本 提供宿舍 伙食补助250
      
      
      [集团]
      Sony东京 25w/y
      intel:研发 研 8k*16 (税前基本工资)
      IBM CDL: 研 7.5k*14 (税前基本工资)
      IBM Sales: 研 5.8k*14 (税前基本工资)
      联想:4000税前.
      联想研究院:5300硕士
      方正电子 5k 硕士,但是只发70%,剩下30%作为奖金 (avivi)
      HP:SALES,5300税前
      
      
      [金融]
      四大全部: 本 5k*13 硕 5.3k*13 (税前基本工资)
      摩根斯坦利: 本 25w/y (税前基本工资)
      BOSH基金深圳:11K/M税前
      招行深圳总行培训生100/Y税后
      四大银行总行:第二年转正后10W/Y
      HSBC:7800税前
      
      
      [消费品]
      NESTLE:4200税前
      P&G:本科6200,研究生7200,博士生9000
      MARS:9150税前
      L'OREAL:4000+税前
      
      
      [其他]
      SHELL:7800税前
      EMERSON:研发7000税前 销售,本,基本工资4K+各种补助奖金等2K左右,税前
      Maersk:本,基本工资5.5K/M,税前
      3院33所 第一年5W,第二年7W (avivi)
      民航数据通信 4500 硕士 (avivi)

      通用电气中国医疗集团,研发,6500-7000/m,不包括福利
      西门子核磁共振,6000/m)(包括餐补,房补)
      通用电气医疗集团,modality specialist,5000/m
      东芝(中国)研发中心,5900/m,房补,车补,另外有2000左右。医疗免费。
      飞利浦东软医疗集团,4500/m,每年18个月工资。
      雅虎中国,研发,7000/m
    还有,陶氏化学IT Center 7100/m,外加800房补,餐补,分红。
       建行总行,硕士,4000+3000/m
      锐捷 3500/m左右
      南瑞 4500/m左右
      可能LZ是个研究生,基本上不会去低薪的电器行业。
      长虹 1500/m
      海信 1500/m
      TCL 1800-3000 集团内部不同公司薪水不同
      康佳 2500/m
      步步高 2500/m
      不过据说家电行业的隐形收入很高,而且拿的是提成,不是奖金。

    西门子家电 4500/M研发 销售:2K左右+提成
      ABB 销售底薪4500+奖金(比底薪稍低)
      GE 销售4K左右+奖金
      施耐德跟ABB收入差不多
      西门子 销售5K多一点
      28所 第一年4万,以后看部门
      东大金智4。3K 第一年6万,第二年8万,第三年10万

    May 23

    【转贴】一个简单的子集产生算法

    在做关联规则挖掘模块的时候,由频繁项集产生关联规则,需要使用到子集产生的算法。比如:
    char[] A={'a','b','c','d',...},集合A中,产生所有A的子集{'a'},{'b'},{'a','b'},{'a','b','c'}...这些。
     
     
    以下是CSDN某高手实现的算法:
     
     //substring.java
     
    public class substring {
      public static void main(String[] args) {
      char[] chs = {'a','b','c','d'};
        SubSet s = new SubSet(chs);
        s.Print();
     }
    }
     
     
    class SubSet
    {
       char[] chs;
       int bits = 0;
     

       public SubSet(char[] chs)
       {
           this.chs = chs;
       }
     
     
       public void Print()
       {
        for(int i = 1;i < (1<<chs.length);i++)  //i小于2的chs.length次方,从0001开始
        {
         for(int j = 0; j< chs.length; j++)
          if( ((1 << j) & i) !=0 )                     //内循环用于确定i的第j位非0。
               System.out.print(chs[j]);                                      
               System.out.println();     
        }
       }
     
    }
     
     
    在例子中,有4个元素的数组枚举出的子集一共有2的4次方减一个(即i的个数减1:1<<chs.length-1),若用二进制为:0000-1111。不考虑0000,则如果第j位为1代表包含数组该下标的值chs[j],那么15个数正好可以完全模拟4个元素产生子集的15种情况(0001,0010......1111分别代表a,b......abcd)。
    这个程序还有一个优势,使用的是移位运算而不是算术运算,可以加快程序执行速度。
    May 21

    使用JDBC

        写访问数据库的java程序,一定要记得添加数据库的.jar驱动程序到项目的构建路径中!!!!使用SWT一定要记得导入本地包的.dll文件!!!
     
     
        今天因为这点小问题程序调了半天,真是郁闷。。。。
    May 14

    阶段性总结 5月14日

        从上个月拔牙到现在已经有近一个月时间了,总结下这一个月的学业情况,希望自己也养成习惯阶段性总结一下,并为下一个阶段制定一些计划。
        这一段时间主要做了几件事情:
        1。搞定那篇数据挖掘的论文。虽然估计是轮不到我来做第一第二作者。谁叫我资历浅。。。今天总算把终稿搞定,短时间内估计不会再搞那个方向了。虽然老板说考虑下多类的算法问题,还说多类的可能也能写一篇论文,但是我实在想不出多类和两类到底有什么本质的区别。。。
        2。大概从4月底快5月的时候开始学习博弈论,到今天基本把完全信息静态博弈看完。现在大概只学了博弈论总共的1/5。。。不过,确实非常有意思。。。有个新想法,把博弈论和分类、聚类应用到决策支持系统,不过可行性分析要留在下周技术报告会之后。
        3。从前天开始做下周技术报告会的PPT,题目是:Introduction to Game Engine。下周一前要搞定。。。也就是说只有今天一天了。。。
        4。平常有时间的时候还看了一些杂七杂八的技术资料,比如如何使用SWT,OpenGL入门。
     
        下阶段的重点将是:OpenGL及相关的图形图象技术;基于Nokia S40平台的使J2ME开发;用Eclipse进行开发;配置Symbian的开发平台;继续学习博弈论。
    May 09

    MSN无法登录的解决办法

        最近在寝室总是无法登录MSN。一登录就现实错误:80048820。上网一查,发现不少人都有这种现象。据称这是MSN的bug,凡是7.0以上的版本都可能出现。。
        网上给出的解决办法是更新系统时间,然后下载一个重新注册MSN的dll的工具运行一下。不过大多数人回复说还是不行。
        解决的办法倒是有一个,而且肯定能成功。那就是首先打开控制面板-》添加删除程序-》删除MSN7.5(或以上版本),然后上网找一个7.0版本的下下来装上,一切OK。。呵呵~~:)除此之外暂时还没找到别的解决办法:(
    May 06

    【原创】Game Theory简介

        Game Theory,翻译成中文就是博弈论,是经济学中比较新兴的学科。看过《美丽心灵》的话应该对这个名词不是那么陌生。。博弈论中有一个著名的理论叫做“纳什均衡”,简单说就是博弈的各方都会根据别人选择的策略来选择一个最佳的策略来作为自己的决策。这个决策被称作“优势策略”。
     
        考虑下面这个经典的问题:囚徒困境。
        警察抓住了两个合伙犯罪的罪犯,但却缺乏证据来起诉他们。如果其中至少有一个罪犯认罪了,就能确认罪名成立。为了得到所需的口供,警察将这两个罪犯分别关押以防止他们串供而选择两个人都不招认。如果两个人都不认罪,则他们会被以妨碍公务罪各判1年徒刑;如果两个人有一个人坦白认罪,那么
    坦白者从轻处罚,立即释放,而另一个则将重判8年徒刑。如果两个人都坦白,则他们两个都将获得5年的刑期。两个人不同决策的情况下被判的刑期可以由下面的表格表示。
     
                                 坦  白        不坦白
                      坦   白   5,5          0,8
         
                      不坦白   8,0          1,1
     
        那么你认为他们会如何选择呢??看到上面的表格,绝大部分的人都认为两个罪犯都会选择拒不认罪。。实际上,两个囚犯都会招,结果两个人都会判5年徒刑。因为自己无法判断另一个人的策略。如果对方选择的是坦白,那么自己如果选择不坦白将会面临一个比较差的结果——判8年。因此两个人都会选择比较稳妥的策略,即都不坦白。其实,坦白是一个优势策略。如果对方选择坦白,那么自己选择坦白将获刑5年,不坦白将获刑8年;如果对方选择不坦白,自己选择坦白讲被立即释放,选择不坦白将获刑1年。因此无论对方如何选择,自己选择坦白都会比选择不坦白获得更少的刑期。这样揭示了一个道理,优势策略未必会得到最优的结果,但是每个人的决策肯定是把自己的利益摆在第一位,而不是集体的利益,因此每个博弈方都会选择自己的优势策略。这就是一个“纳什均衡”。
     
        纳什均衡是博弈论中的一个经典基础理论,实际上现实生活中很多涉及到决策的问题都可能牵扯到博弈论。下面来介绍基本经典的博弈论书籍:
     
    1。策略思维:商界、政界及日常生活中的策略竞争
                                             
        这是我个人非常喜欢的一本书。当年去上海实习的时候从复旦大学的书店里面带的一本书回来,记得在长沙半年之后才在书店看到有的卖。该书用许多活生生的例子,向没有经济学基础的读者展示了博弈论策略思维的道理。书里面没有深奥的微观经济学和数学的公式,但是有很多现实生活中的决策案例。两位作者是耶鲁大学和普林斯顿大学精通博弈论的教授。本书以讲故事取胜。简而言之,这是关于了解对手打算如何战胜你,然后你战而胜之的艺术。怎样打赢一场网球,少数如何战胜多数,为什么要“喜爱”你最讨厌的对手等等,都在讨论之列。里面的推理过程非常有意思!!:)
     
     
    2。经济博弈论(第二版)
                                             
        这本书适合做一本博弈论的教材。不过这本书跟上海财经大学出的另一本叫《博弈论》(施锡铨 著)的书相比公式还不算太多。适合有一定微观经济学和数学基础的人看。前阵子在地摊上以3折的价格淘到,嘿嘿~~。
     
     
    3。《博弈论》
                                              
        这本不是上面介绍的施锡铨著的那本(虽然名字一样)。这是一本经典的博弈论教材,是博弈领域的两位领军人物的集大成之作,囊括了迄今为止除演化博弈之外的所有博弈论的理论和方法、代表了博弈论发展的最高水平!!这是一本巨厚的书,A4的版面,还有68块钱的高价。里面光复杂的数学公式就看的人头大。。。本书适合专业的想深入研究博弈论的人士阅读使用,相信大多数人都不是这一型的。。
     
    March 21

    Linux

        昨天是fedora社团正式发布Fedora Core 5 的日子。。。没想到redhat放弃了桌面linux后,Fedora Core这么快已经发布了第五个版本了。。。
     
        以前在网上看过不少人评论说Fedora的桌面linux系统整体感觉不如Suse Linux。。。不过偶的机器里面已经存储了4个linux系统的安装文件-Fedora Core 4、Redhat Enterprise 4 Advanced Server、Suse Linux Desktop和Suse Linux Enterprise版,过一阵子装一个玩玩。。。