矩陣變數與結構變數的相互包含
矩陣與資料結構實體,做為變數與一般的變數沒什麼兩樣,它們都可以做為更大的矩陣的元素,或則是更大的結構的元素。例如
struct Block{
char color[10];//其實字串就算是字元的矩陣
double size[3];//這只是說字串並不是特例
double mass};
宣告了名為Block 的資料格式 或
typedef struct {
char color[10];//其實字串就算是字元的矩陣
double size[3];//這只是說字串並不是特例
double mass} BlockStr_t;
定義出新的資料型態 BlockStr_t。
資料結構型態內的尺寸欄用三維矩陣來容納長寬高,也就是說資料結構格式內可以容許以矩陣做為欄位。
又如:
struct Ball Balls_str[] = {{"red", 3.0},
{"green", 5.0},
{"blue", 10.0}};
或
BallStr_t Balls_str[] = {{"red", 3.0},
{"green", 5.0},
{"blue", 10.0}};
Balls_str[],是一個以資料結構實體為元素的矩陣 。
指名欄位初始值來初始化資料結構實體
上一個範例中,以結構為成員的矩陣Balls_str[],在初始化時,可以使用大括號包含大括號,這個方式可以在宣告一個大型結構變數的同時一次性初始定義它的值,取代掉一欄一欄用等式初始的煩複過程。
例如
BlockStr_t block1_str ={{"green"}{1.0,1.0,1.0}{0.5}};
表面上看起來是一個很方便的初始化方式。然而如果這個結構變數欄位中有欄位,而且互包的層次有許多層,每層的欄位內容又長短不一時,很容易就因打錯字,或多打,少打一欄,而發生移位錯誤。
利用C語言提供的指名欄位初始化(designations)方式,可以避免初始值必需正確排序的困難。
BlockStr_t block1_str={ .color="green" , .size={1.0,1.0,1.0}, .mass=0.5};
如上例,利用『.欄名 =初值』的語法,可以指定資料結構中特定欄位的初始值。
用指名欄位初始的方式,指名的順序不影響初始化的結果。上例也可以寫成 BlockStr_t block1_str={ .size={1.0,1.0,1.0}, .color="green" , .mass=0.5};
指名初始化中,如果有一個欄位沒有被指名初始,則它的內容,會維持這個資料結構被定義時的初值,通常是0。
例如
BlockStr_t block1_str={ .size={1.0,1.0,1.0}, .color="green"}; 則 block1_str.mass的值會是0。
以巨集字串來初始化資料結構實體
利用前介紹過的巨集字串取代功能,針對每一個欄位指定不同的巨集字串名稱,再將各欄位替化初始字串組織成一個更大的巨集替代初始字串,做為最終初始化所用的初始用巨集字串。這也可以解決排序不易的困難。
例如
//color 欄第一個初始值巨集
#define blockcolor1_ini "green"
//size 欄第一組三元初始值巨集
#define blocksize1_ini {1.0,1.0,1.0}
//mass 欄第一個初始值巨集
#define blockmass1_ini {0.5}
//集合各欄巨集組成第一個 block結構的初始字串
#define block1_ini {blockcolor1_ini,blocksize1_ini,blockmass1_ini} :
//宣告,定義,並且初始化 block資料結構型態,名為block1_str的一個資料結構
BlockStr_t block1_str = block1_ini;
這樣的做法,我們一方面比較容易確認初始值與被初始欄位之間的對應關係。
另一方面可以把上述定義巨集的區塊,分割出來放到xxx.h檔或xxx.cfg內,再於xxx.c檔的啟頭段引入。
#include block1.cfg
BlockStr_t block1_str = block1_ini;
main(){ }
則也可以維持不變的xxx.c程式碼,只要重新編輯前置碼檔block1.cfg,就可以輕鬆的更改資料結構實體初始化的設定。
注意:利用定義巨集字串取代,並集中這些參數或起始值的巨集定義在同一個xxx.h檔或xxx.cfg檔中,除了可以免除太多層大括號的混亂,最主要的功效是,把會被改動的常數值,集中到xxx.h檔中,可免除常數參數或初始值散佈在C程式碼中各處,而產生修改時被遺漏的機會。