2011年6月20日 星期一

"STATIC" - C/C++ Programming

"static" : a programming tag that confuses and troubles many people, and so am I of course.

The following content and information is referenced from others' blog:

  • Static Variable (靜態變數):
  • static 放在 variable 前時,代表這個 variable 的存活時間和整個程式一樣長。也就是 life time 跟整個 Process 一樣長,而 scope 則維持不變。
    Example:
    執行結果 x=5 y=1 TestFunction 會對 x , y 配置記憶體空間並進行 initial,當 TestFunction 結束的時候,會將 y 的記憶體歸還,下次呼叫時再重新配置一次;而x被宣告成static,所以x的記憶體不會歸還,延用著上次的值。
    碎碎念1:似乎可以看成被宣告成 static 的變數,其實就是 global 的了,只是因為 x 是宣告在 TestFunction 裡,所以只能在 TestFunction 裡用。
    碎碎念2:如果把 x 宣告在外面當成 global,那 int x; 和 static int x; 是一樣的。
    碎碎念3:在 TestFunction 裡,static int x=0; 的初始化只會做一次。如果寫成 static int x; x=0; 那結果就會跟 y 一樣。

  • Static Member Variable (靜態成員變數):
  • 在 class 裡把 member variable 宣告成 static,代表他是「與 class 相關連」,而不是「與物件相關連」。他獨立配置記憶體,獨立於 class 的任何物件而存在,這個 class 產生的所有物件共用使同一個 static member variable,甚至不需要有物件也能夠被使用。
    因為 static member variable 不屬於任何物件,所以必須定義在外面。與一般成員變數不同,static member variable 並不是經由 constructor 初始化,而是在定義時被初始化。
    碎碎念1:可以看做是一個存在於某個 class 的 global variable。

  • Static Member Function (靜態成員函式):
  • 如果static member variable是private的
    如果 static member variable 是 private 的,那就沒有辦法直接取了,那該怎麼辦呢?寫一個 Get 的 member function?
    這樣不是很奇怪嗎?因為 m_nNum 在不是 private 的時候,可以不用產生物件就可以存取,但是用 Get member function 卻要產生一個物件。所以這樣的方法並不好,因此,就要把 Get member function 也宣告成static的。
    static member function 也跟 static member variable 一樣,獨立於物件存在。可以在沒有物件產生的狀況下被使用,所以他不能使用 this,也不能存取 class 裡的一般成員變數,當然也不能使用一般成員函式了。
    也就是說,static member function 只能存取 static member variable。
    那如果真的想用呢?就要用以下的方法:
    執行結果:
    A::m_nNum=0
    建立物件a1
    A::m_nNum=0
    a1.m_nNum=0
    a1.GetNum2()=10
    a1.StaticGetNum3()=20

    建立物件a2
    A::m_nNum=0
    a2.m_nNum=0
    a2.GetNum2()=10
    a2.StaticGetNum3()=100  // 把a2的m_nNum3從20設成100
    a1.StaticGetNum3()=100  // Question!?
    a1.GetNum3()=20
    值得注意的是 a1.StaticGetNum3()=100,a1 的 m_nNum3 是 100 嗎?a1 的 m_nNum3 明明就是20,而 a2 的 m_nNum3 才是100,那為什麼這裡會錯了呢?
    主要的問題是來自於 m_pThis,我們為了讓 static member function 可以存取一般成員函式和成員變數,所以使用 m_pThis 指向自己來取得一般成員函式和成員變數,而且為了讓 static member function 可以使用 m_pThis 指標,還把 m_pThis 指標宣告成 static 的。
    宣告成 static 就表示他是所有物件共用的,所以當產生 a1 物件時,m_pThis 是指向 a1 物件的,而產生 a2 物件時 m_pThis 就改指向 a2 物件了,所以就算透過 a1 物件取得 m_pThis,也都會取得 a2 物件了。
    碎碎念1:要避免這問題,只能想辦法確保 A 類別只會產生1個物件? singleton ?沒有別的辦法嗎? 有的!就是把物件自己當成參數傳進 static member function 裡。
referenced from - C++的static @ 伊卡洛斯之翼

「百年千書 經典必讀」數位閱讀計畫內容

2011年6月17日 星期五

「極致」於我

       「極致」,一個極抽象的詞彙,在你的心目中,在每一個人的心中,會追求一個極致的目標,這是一個理想;抑或是個夢想,捫心自問 ─ 我所追求的極致是什麼?

        炎夏的夜晚,跟好友同事三五成群在頂樓的天台上討論心中的想法,喝著尚青的台啤,提到了「極致」這個詞,一時間我真得不知道該如何回應這個話題,就工作上來說,如何達到心中所謂的極致,我所認為的極致是什麼?作為一個軟體工程師,我所祈求能達到的極致是什麼:

  • 使用者介面的便利
  • 程式效率的優化
  • 應用軟體的實用與獨特
  • 善用各種輔助工具

        就目前來說,我有把握做到的有哪些?答案是「沒有」,我真的無法將這些事情每樣都做到極致,人的能力透過學習不斷在進步,難有稱為極致的一日,我能把握的是,我的確是不斷在進步中,從進步中一一修正自己過去錯誤的地方,一步步達到自己心中所謂的極致,「創新是建立在傳統的基石之上,成功是萌發於過去的失敗之中」,能看得又高又遠,是因為站在巨人的肩膀上,敢說得言之鑿鑿,是由於知道自己有幾斤幾兩重。

        最近面臨工作上的一些瓶頸,想跳出目前的窠臼,卻不知從何著手,主管離開了,缺乏有一個有想法的領導者,我真得必須知道自己現在做得是什麼,不然我該如何進步,與朋友們的小小喇賽是一個好的切入點,試圖想從中尋找自己的目標所在,很感謝能與這群好夥伴好朋友共事,雖然目前還無法找到突破點,但是我相信會慢慢的有路可循,找回自己對工作上的熱情與興趣。

P.S.我絕對不會說......其實我今晚最感興趣的是同事家中的那片藍光謎片 -.-"

2011年6月7日 星期二

porting tslib (abstraction layer for touchscreen) to ARM Platfrom

Step by Step:
my environment:
OS: Ubuntu 10.04
Cross-compiler:
  - CC   = linux-arm-gcc (4.1.2)
  - CXX = linux-arm-g++ (4.1.2)

  1. Download tslib source code
    • download tslib tar or zip file from http://tslib.berlios.de/
    • my download file version is named kergoth-tslib-1.0-94-gd4073fe.zip
  2. Install dependency libraries
    • sudo apt-get install m4 autoconf automake libtool
  3. set tslib install path
    • export PREFIX=/home/myname/tslib/BUILD 
      #set INSTALL PATH by your choice
  4. execute autogen.sh
    • ./autogen.sh
    • After this command finished, it generates configure file for tslib.
  5. configure tslib
    • ./configure --build=i386-linux --host=arm-linux --target=arm --prefix=$PREFIX ac_cv_func_malloc_0_nonnull=yes
  6. make; make install

2011年6月2日 星期四

[C++] The significance about - extern "C"

extern "C" 是C++特有的組合關鍵字,在C裡並沒有這個的組合,僅有extern這個關鍵字!

為什麼C++會需要這樣的關鍵字組呢? 原因是C++它有一個複載(overloading)的功能,也就是說同樣的函式名稱可以有多個定義只要參數簽名不同即可。
比如說C++裡可以有以下的二個宣告


bar(int i, int j);

bar(double i, double j);

這二個函式都是同樣的名字叫foo,僅參數型式不同。然而在C語言裡是不被允許的! C++是如何處理這同名的函式呢? 其實他在編譯時會偷偷的把這二個函式名變成不同的名字,舉例來說bar(int i, int j)可能會被改成_bar_int_int(每種compiler產生不太一樣),而另一個則被改成_bar_double_double。這技術稱 Mangling。

問題來了! 當我們希望C++不要偷換函式名時該怎麼辦? 於是就有了extern "C" 這個關鍵字組出現了。這個字組就是請C++不要自己又偷天換日,請它保留原名。所以當我們宣告一個函式如下時:

extern "C" bar(int i, int j);

編譯器就不會把bar變成_bar_double_double。

實際使用的注意事項:

1/ 當C++使用C的函式庫(library)時,C++不能直接套用C的header檔。因為他會把header裡的宣告給mangleing了。所以他必須使用如下:

extern "C"
{
#include "C_LIB.h" //C_LIB 是由C語言所寫的。
}

2/ 相反的,在C語言的編譯器裡若要使用由C++所寫出來的C函式庫,那麼也不能直接的使用C++的header檔。因為此header檔必然存在 extern "C" 這個關鍵字組,而這字組C語言是不認識的。所以必需要把C++的header檔裡的extern "C" { } 移除後才可以讓C編譯器使用。

  • 注意事項


  • 一組多載函數中, 只能有一個函數被指明為 "extern C", 因為符號修飾後的關係, ex:

    void abc(int);
    "extern C" void abc(char);
    "extern C" void abc(float);
    

    使用 C 方式的修飾符號是 _函數名,因此是 _abc, 所以當第2組指明 "extern C" 也是 _abc 那麼兩組 C 函數的符號就重複了,此檢查在函數的多載就可以,但是同一個 scope 中函數沒有多載化就無法檢查出,更確切的說,"extern "C" 不受 namespace or class 修飾的影響, 因此同一編譯單元中只能有一個同名函數為 "extern C", 否則會有錯誤 ,ex:

    namespace N
    {
    extern "C" void abc(){} // _abc
    
    }
    
    extern "C" void abc(){} // _abc
    


    編譯時產生相同符號 _abc 函數定義故錯誤,由於 extern "C" 不受限於 namespace 的修飾因此將產生一個有趣現象也就是宣告和定義可以在不同的 namespace 出現。語法層面上的檢查就如同一般,而當語法檢查通過後產生符號時,extern "C" 的定義其符號不帶有 namespace 的修飾;同樣的,呼叫者其符號也不帶有 namespace 的修飾,ex:


    namespace Foo
    {
    extern "C" void abc() {} //有定義, 生成符號時, 不受限於 namespace Foo 修飾故符號為 _abc
    }
    
    namespace Bar
    {
    extern "C" void abc(); //純宣告 
    }
    
    int main()
    {
    Bar::abc(); //函數呼叫, 生成符號時, 不受限於 namespace Bar 修飾故符號為 _abc, 事實上鏈結到 ::Foo::abc()
    }
    

    還有下面如此鏈結錯誤的狀況:
    由於extern "C" 沒有多載功能,不論是 void abc() 或是 void abc(int a) 都將被以 _abc 來做為函式名稱,這是極度危險的.


    1.c
    extern "C" void abc();
    int main()
    {
    abc();
    }
    

    2.c
    #include
    extern "C" void abc(int a)
    {
    printf("%d",a);
    }
    

    當 1.c 和 2.c link 時可以,因為 c 沒有將參數名稱當作函式修飾名稱的一部分,故也就沒有多載,將 "C" 拿掉 link 時就會錯誤,因為會以 c++ 的方式來編譯。

    資料來源:C++中關於extern "C"的意義