發現許久沒有來園子里逛了,一來是工作了,的確很忙,二來是手的確有點懶。想寫點東西,找來找去,還是對這個園子有感情。
最近發現懶惰真的是一個很容易養成的習慣,它會慢慢吞噬掉一切。就項目而言,壓力的確比學生時要繁重許多,但條理性似乎更加重要。隨手記下,隨時總結總歸是好的,一個回頭,就不知道什么是時候是個頭了。
所以半年多的經驗來看,一定要及時的總結項目,要把最新鮮的,最熱氣騰騰的東西記錄下來。
對自己回顧是一個幫助,對他人入門也是個捷徑。
養成及時總結的習慣很重要。
posted @
2010-11-16 23:34 Sandy 閱讀(365) |
評論 (0) |
編輯 收藏
今天是一個非常開心的日子,我拿到了我夢寐以求的一家公司的offer,可以繼續沿著夢想的道路繼續前進,開心。
首先感謝默默支持我的人,在這一路尋找的路上,有過很多挫折,謝謝他們給我的力量,讓我越挫越勇。
其次感謝一次次面試中給了我很多幫助的面試官,其實面試是一個互相學習的機會,而且每一次的肯定都是對能力的一種肯定,給了我很多信心。最后可能由于各種原因,與一些公司擦肩而過,也衷心祝愿這些公司的發展越來越好。
最后感謝給了我很多建議的人,讓我一路堅持夢想的走下來。 軟件開發,是我熱愛的一個方向,我也希望能夠沿著這條路繼續走下去。
小小廣告,如果你的網絡很慢,不妨試試Opera的Turbo加速,不一般的體驗啊!
posted @
2009-12-21 22:29 Sandy 閱讀(504) |
評論 (3) |
編輯 收藏
摘自:
http://liuaigui.blog.sohu.com/86494742.html線程安全的(Thread-Safe):如果一個函數在同一時刻可以被多個線程安全地調用,就稱該函數是線程安全的。線程安全函數解決多個線程調用函數時訪問共享資源的沖突問題。
可重入(Reentrant):函數可以由多于一個線程并發使用,而不必擔心數據錯誤。可重入函數可以在任意時刻被中斷,稍后再繼續運行,不會丟失數據。可重入性解決函數運行結果的確定性和可重復性。可重入函數編寫規范為:
1、不在函數內部使用靜態或全局數據
2、不返回靜態或全局數據,所有數據都由函數的調用者提供。
3、使用本地數據,或者通過制作全局數據的本地拷貝來保護全局數據。
4、如果必須訪問全局變量,利用互斥機制來保護全局變量。
5、不調用不可重入函數。
兩者之間的關系:
1、一個函數對于多個線程是可重入的,則這個函數是線程安全的。
2、一個函數是線程安全的,但并不一定是可重入的。
3、可重入性要強于線程安全性。
比如:strtok函數是既不可重入的,也不是線程安全的。加鎖的strtok不是可重入的,但線程安全。而strtok_r既是可重入的,也是線程安全的
之所以會去查這個問題,是在考試中遇到過考strtok這個問題是否可用于多線程。自己從使用的角度上感覺不安全,但是究其原因卻不是很明白。查了一下,居然涉及到函數的線程安全。
在另一篇博文中,是這樣解釋的:
strtok不是一個線程安全的函數。因為根據其定義,它必須使用內部靜態變量來記錄字符串中下一個需要解析的標記的當前位置。但是,由于指示這個位置的變量只有一個,那么,在同一個程序中出現多個解析不同字符串的strtok調用時,各自的字符串的解析就會互相干擾。(摘自:
http://hi.baidu.com/pigfanfan/blog/item/72816c958d63e743d1135ebf.html)
怎么避免呢?
我們可以利用另一個函數:strtok_r,這個是一個線程安全的函數——strtok_r,以此來代替strtok。
posted @
2009-10-22 17:33 Sandy 閱讀(1597) |
評論 (0) |
編輯 收藏
轉:C++ pair用法
摘自:
http://hi.baidu.com/lucene1983/blog/item/83bb68351d12ffbed1a2d3fe.html1 pair的應用
pair是將2個數據組合成一個數據,當需要這樣的需求時就可以使用pair,如stl中的map就是將key和value放在一起來保存。另一個應用是,當一個函數需要返回2個數據的時候,可以選擇pair。 pair的實現是一個結構體,主要的兩個成員變量是first second 因為是使用struct不是class,所以可以直接使用pair的成員變量。
2 make_pair函數
template pair make_pair(T1 a, T2 b) { return pair(a, b); }
很明顯,我們可以使用pair的構造函數也可以使用make_pair來生成我們需要的pair。 一般make_pair都使用在需要pair做參數的位置,可以直接調用make_pair生成pair對象很方便,代碼也很清晰。 另一個使用的方面就是pair可以接受隱式的類型轉換,這樣可以獲得更高的靈活度。靈活度也帶來了一些問題如:
std::pair<int, float>(1, 1.1);
std::make_pair(1, 1.1);
是不同的,第一個就是float,而第2個會自己匹配成double。
以上是從網上找來的資料,我又查了一下關于pair的定義,其定義是一個模板結構。
// TEMPLATE STRUCT pair
template<class _Ty1,
class _Ty2> struct pair

{ // store a pair of values
typedef pair<_Ty1, _Ty2> _Myt;
typedef _Ty1 first_type;
typedef _Ty2 second_type;

pair()
: first(_Ty1()), second(_Ty2())

{ // construct from defaults
}

pair(const _Ty1& _Val1, const _Ty2& _Val2)
: first(_Val1), second(_Val2)

{ // construct from specified values
}

template<class _Other1,
class _Other2>
pair(const pair<_Other1, _Other2>& _Right)
: first(_Right.first), second(_Right.second)

{ // construct from compatible pair
}

void swap(_Myt& _Right)

{ // exchange contents with _Right
std::swap(first, _Right.first);
std::swap(second, _Right.second);
}

_Ty1 first; // the first stored value
_Ty2 second; // the second stored value
};
make_pair同樣也是一個模板函數。其定義如下:
template<class _Ty1,
class _Ty2> inline
pair<_Ty1, _Ty2> make_pair(_Ty1 _Val1, _Ty2 _Val2)

{ // return pair composed from arguments
return (pair<_Ty1, _Ty2>(_Val1, _Val2));
}
posted @
2009-10-15 11:09 Sandy 閱讀(12047) |
評論 (0) |
編輯 收藏
有這么一個關于虛函數和虛繼承的問題,如下:
class A
{
char k[3];
public:
virtual void aa();
};
class B: public virtual A
{
char j[3];
public:
virtual void bb();
};
class C: public virtual B
{
char i[3];
public:
virtual void cc();
};
請問sizeof(A), sizeof(B), sizeof(C)分別為多少?
對于A, 我們很清楚的知道,其大小為8。
對于B,考慮到虛繼承和自身的虛函數,我們也可以算出來起大小為8+8+4 = 20
對于C,其大小為20+8+4 = 32。
其中 4為虛繼承所占用的指針。
這個看上去沒有什么問題。但是當我把虛繼承去掉以后,這里卻有了一些變化?
首先,我猜想了一下,A是8,B是16,C是24。
可惜結果和我想的不一樣,答案是8, 12, 16。很有規律的一個數字。
從A到B,只增加了4。什么原因呢?
在http://www.diybl.com/course/3_program/c++/cppjs/2007927/74925.html這里介紹了一些
The existence of virtual function(s)
Existence of virtual function(s) will add 4 bytes of virtual table pointer in the class, which will be added to size of class. Again, in this case, if the base class of the class already has virtual function(s) either directly or through its base class, then this additional virtual function won't add anything to the size of the class. Virtual table pointer will be common across the class hierarchy. That is
class Base {
public:
...
virtual void SomeFunction(...);
private:
int iAMem
};
class Derived : public Base
{
...
virtual void SomeOtherFunction(...);
private:
int iBMem
};
In the example above, sizeof(Base) will be 8 bytes--that is sizeof(int iAMem) + sizeof(vptr). sizeof(Derived) will be 12 bytes, that is sizeof(int iBMem) + sizeof(Derived). Notice that the existence of virtual functions in class Derived won't add anything more. Now Derived will set the vptr to its own virtual function table.
派生類和基類擁有相同的虛函數表。
但似乎虛繼承的時候,又擯棄了這一做法。
所以兩個是有所區別的。
posted @
2009-10-07 22:43 Sandy 閱讀(1964) |
評論 (2) |
編輯 收藏
今天在看面試寶典,注意到上面所說浮點數在內存里和整數的存儲方式不同,但究竟有何不同呢?
在網上搜了一下:
在http://blog.csdn.net/djsl6071/archive/2007/03/16/1531336.aspx中介紹了浮點數在內存中的存儲方式,覺得不錯,轉過來。
浮點數在內存中的存儲方式
浮點數保存的字節格式如下:
地址 +0 +1 +2 +3
內容 SEEE EEEE EMMM MMMM MMMM MMMM MMMM MMMM
這里
S 代表符號位,1是負,0是正
E 偏移127的冪,二進制階碼=(EEEEEEEE)-127。
M 24位的尾數保存在23位中,只存儲23位,最高位固定為1。此方法用最較少的位數實現了
較高的有效位數,提高了精度。
零是一個特定值,冪是0 尾數也是0。
浮點數-12.5作為一個十六進制數0xC1480000保存在存儲區中,這個值如下:
地址 +0 +1 +2 +3
內容0xC1 0x48 0x00 0x00
浮點數和十六進制等效保存值之間的轉換相當簡單。下面的例子說明上面的值-12.5如何轉
換。
浮點保存值不是一個直接的格式,要轉換為一個浮點數,位必須按上面的浮點數保存格式表
所列的那樣分開,例如:
地址 +0 +1 +2 +3
格式 SEEE EEEE EMMM MMMM MMMM MMMM MMMM MMMM
二進制 11000001 01001000 00000000 00000000
十六進制 C1 48 00 00
從這個例子可以得到下面的信息:
符號位是1 表示一個負數
冪是二進制10000010或十進制130,130減去127是3,就是實際的冪。
尾數是后面的二進制數10010000000000000000000
在尾數的左邊有一個省略的小數點和1,這個1在浮點數的保存中經常省略,加上一個1和小數
點到尾數的開頭,得到尾數值如下:
1.10010000000000000000000
接著,根據指數調整尾數.一個負的指數向左移動小數點.一個正的指數向右移動小數點.因為
指數是3,尾數調整如下:
1100.10000000000000000000
結果是一個二進制浮點數,小數點左邊的二進制數代表所處位置的2的冪,例如:1100表示
(1*2^3)+(1*2^2)+(0*2^1)+(0*2^0)=12。
小數點的右邊也代表所處位置的2的冪,只是冪是負的。例如:.100...表示(1*2^(-1))+
(0*2^(-2))+(0*2^(-2))...=0.5。
這些值的和是12.5。因為設置的符號位表示這數是負的,因此十六進制值0xC1480000表示-
12.5。
關于多字節數據類型在內存中的存儲問題
int ,short 分別是4、2字節。他們在內存中的存儲方式下面舉個例子說明。
int data = 0xf4f3f2f1;
其中低位存放在編址小的內存單元,高位存放在編址高的內存單元
如下:
地址:0x8000 0x8001 0x8002 0x8003
數據: f1 f2 f3 f4
根據IEEE在1985年制定的標準來處理浮點數
單精度浮點數用4字節,包括1位符號位s(整數為0,負數為1),8位指數位e,23位有效位f
浮點型使用的是科學計數法,比如十進制的12345可以表示為1.2345 * 10^4(表示10的4次冪)
用二進制表示為 1.1000000111001 * 2^13
所以計算機中用浮點數表示12345這個十進制應該是這樣的,s位為0,因為是正數,指數位為13+127=140(127為單精度浮點數偏移值,為了表示只有小數部分的數),有效位為1000000111001
計算的時候用 (-1)^s * 1.f * 2^(e-127) ,結果就是 1* 1.1000000111001 * 2^(140-127=13) ,和我們剛才表示的一樣
還比如,十進制小數0.125轉換為二進制小數0.001可以表示為 1* 1.0 * 2^(124-127=-3)
double,雙精度浮點數有1位符號位、11位指數位和52位有效數
謝謝,和我找的資料差不多:)
知道公式
n=(-1)^s*m*2^e
e=|E|-bias
bias = 2^(k-1)-1(k為E的位數)
m=|1.M|
知道12345在內存中的10進制表示以后
0x4640e400 = 0(100 0110 0)<100 0000 1110 0100 0000>
括號中的數字為|E| = 140 所以e=140-127=13
尖括號中的數字為m=|1.M|=|1.100000011100100|=1.506958008
ok,
代入公式n = (-1)^0*1.506958008*2^13=12345
完工!!
本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/edivista/archive/2009/06/07/4248794.aspx
本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/edivista/archive/2009/06/07/4248794.aspx
posted @
2009-10-02 20:51 Sandy 閱讀(1069) |
評論 (0) |
編輯 收藏
DLL, 動態鏈接庫, Dynamic-link library.一直以來都是Windows操作系統的基石。Window應用程序編程接口提供的所有函數都包含在DLL中。其中三個最重要的DLL分別是Kernel32.dll,User32.dll,GDI32.dll。Kernel32.dll ,包含的函數用來管理內存、進程以及線程;User32.dll包含的函數用來執行與用戶界面相關的任務,如創建窗口和發送消息。GDI32.dll,包含的函數用來繪制圖像和顯示文字。Windows Mobile中重要的DLL是Coredll.dll.
Windows系統廣泛使用DLL,那么我們使用DLL的理由是什么?下面是在《Windows 核心編程中》摘錄的一部分:
一是擴展了應用程序的特性;
二是簡化了項目的管理;
三是有助于節省內存;
四是促進了資源的共享;
五是促進了本地化;
六是有助于解決平臺間的差異;
七是可以用于特殊目的。
目前用到的地方在 節省內存、資源共享、本地化、特殊目的。這幾個是我在項目中見過的。DLL如何使用呢?一般有兩種方法,一是隱式載入時鏈接(implicit load-time linking)和顯示運行時鏈接(explicit run-time linking)。
隱式鏈接,常用的方法是將DLL的頭文件和LIB文件包含到執行文件程序中,相應DLL放到執行文件對應的目錄。基本就OK了。
例如:
DLL為MyLib.dll,其頭文件為MyLib.h, LIB文件為MyLib.lib。
我們在執行文件中使用是,需要做如下操作:
#include "MyLib.h"
#pragma comment(lib, "MyLib.lib")
即可實現隱式調用,變量、函數、類就可實現調用。
這里lib文件非常小,它并不包含任何函數或變量,它只是列出了所有被導出的函數和變量的變量名,具體的實現在dll文件中。編譯階段不包含Lib文件會出錯的。
顯示鏈接,在應用程序運行的過程中,顯示地載入所需的DLL。
一般可以使用LoadLibrary和FreeLibrary來實現加載和卸載DLL。那么如何判斷一個DLL是否已經被映射到了進程的地址空間中?我們可以使用GetModuleHandle.
如:
HMODULE hInstDll = GetModuleHandle(TEXT("MyLib"));
if (hInstDll == NULL)
{
hInstDll = LoadLibrary(TEXT("MyLib"));
}
我們已經知道如何顯示加載DLL,那如何顯示調用其中的變量、函數、類呢?
例如在DLL中,我們有一個變量 g_nResult, 函數Add,我們在執行程序中如何調用呢?可以利用GetProcAddress。
對于變量:
int nResult =*(int*)GetProcAddress(hInstDll, "g_nResult");
對于函數:
typedef int (*FUNC)(int, int);
FUNC pfn = (FUNC)GetProcAddress(hInstDll, "Add");
這是今天學習到的關于DLL的一點知識。
posted @
2009-10-02 16:43 Sandy 閱讀(692) |
評論 (0) |
編輯 收藏