2017年3月27日 星期一

using namespace std

一開始學C++便看到每個程式的最頂,#include的下方都會有一句:
using namespace std;

所有C++ Standard Library中的class(例如string、map、ifstream)都屬於std這個namespace下。當你要在自己的程式內使用它們時,便需要在前方加上std::,例如std::string。但如果使用了上述那句的話,便不需要加上std::,而是讓compiler自動幫你加。

只不過這樣做的缺點就是當你自己有class和C++ Standard Library中的任何一個class撞名,compiler便可能會選錯namespace,又或者直接顯示ambigious的錯誤。解決這問題的方法主要有兩個:

  1. 盡量在.cpp中加入這一句,而非.h,因為header file很容易被其他文件include,讓缺點擴散(?)
  2. 指定某些class使用std namespace,而非一刀切全部用std。代碼如下:
using std::string;
using std::cout;
using std::ifstream;

2017年3月6日 星期一

Struct Member Alignment

無論用TCP還是UDP收資料都需要解碼(又叫decode或者拆packet),即是把收回來的byte array根據protocol來處理,從而抽取一些有用的資料。而我見過有些code是直接用type cast把byte array轉換成struct,然後很神奇地就會順著struct的member的順序來填入這些member variable了。

一開始我上網搜尋看到有人指出這個行為並非C++標準,而且OS可能會自行把struct的member拆開令它們在記憶體中不是連續的(例如Windows會以4個Bytes為一個DWord以提升效率),這樣的話type cast就會搞到解碼錯誤,但只要加上一些OS提供的特殊語法就沒有問題。

例如Windows的話,要在struct前後加上#pragma pack,並且在前面說明以1 Byte為pack的單位。
#pragma pack(1)
struct ABC{
/* member variables */
}
#pragma pack()

當然,我覺得始終最好的方法是在constructor寫明怎樣解碼,這樣除了比較清晰容易檢查之外,也是一個跨平台的解決方法。

參考資料:
http://blog.xuite.net/kamory0931/fightdreamer/52223417-%E7%B5%90%E6%A7%8B%E7%9A%84%E5%B0%8D%E9%BD%8A(Struct+Member+Alignment)