C關鍵字pragma pack,C#關鍵字StructLayout,網路上能找到的資料極多
最保險的寫法,資料用1個byte的寬度去對齊記憶體
C:#pragma pack(1)
C#:[StructLayout(LayoutKind.Sequential, Pack =1)]
有些系統為了效能,程式內資料會用4或8個bytes的寬度去對齊記憶體,
但把資料列印到檔案或透過網路轉送時,讀寫(收發)外部資料就要做額外處理
把資料(bytes)給客戶時,客戶讀完一個欄位後,可能要略過3或7個bytes,再讀下一個欄位,
略過的bytes,很有可能是亂碼,客戶閱讀或解析上會很不方便
因此除非有特例需要,通常我會用pragma pack(1)去對齊記憶體,
以下紀錄我寫新的class(.h/.cpp)時常用的排版
#ifndef _MY_NEW_NAMESPACE_MY_NEW_CLASS_H
#define _MY_NEW_NAMESPACE_MY_NEW_CLASS_H
#include <standard library>
#include "third party library"
using namespace OtherNamespace;
using OtherNamespace::OtherClass;
#pragma pack(1)
namespace MyNewNamespace
{
//宣告
class MyNewClass
{
public:
//
};
//實作
}
#pragma pack()
#endif
把資料列印到檔案或透過網路轉送時,如果要對齊特定的資料格式,
常見的做法,會塞空白' '填充,避免亂碼
考量相容性與移植性,在程式碼上自行定義pragma pack比較好,
不同平臺系統上,預設的pragma pack可能會不一樣
20230318補充,程式的進入點,main的排版,我通常會寫成
#pragma pack(1)
int main(const int argc, const char *argv[])
{
//
return EXIT_SUCCESS;
}
#pragma pack()
#endif
標準規範是寫成int main(int argc, char *argv[])即可,不過不會去改動的變數,我習慣在前面加上const,
原因同之前寫的,in 參數修飾詞 (C# 7.2以上支援),
避免不小心手滑改到不該改的資料,減少日後程式出錯的機率
程式結束時,沒錯return EXIT_SUCCESS,有錯return EXIT_FAILURE,也是標準的寫法
參考
Both EXIT_SUCCESS and the value zero indicate successful program execution status (see exit), although it is not required that EXIT_SUCCESS equals zero.
觀察幾個常見的平臺,EXIT_SUCCESS似乎都是定義0,但標準規範沒寫一定要是0,
EXIT_SUCCESS的實際數值,應該是由各平臺自行決定,
EXIT_FAILURE則可能各自有複雜的定義,只要不等於EXIT_SUCCESS即可
譬如
Windows上0代表正常關閉,1~15999微軟有定義不同的錯誤碼