高端型網(wǎng)站制作永久免費google搜索引擎
C語言——結(jié)構(gòu)體與共用體
- 結(jié)構(gòu)體
- 共用體
結(jié)構(gòu)體
如果將復(fù)雜的復(fù)雜的數(shù)據(jù)類型組織成一個組合項,在一個組合項中包含若干個類型不同(當(dāng)然也可以相同)的數(shù)據(jù)項。 C語言允許用戶自己指定這樣一種數(shù)據(jù)結(jié)構(gòu),它稱為結(jié)構(gòu)體。
結(jié)構(gòu)體的語法定義:
struct 結(jié)構(gòu)體名
{
成員列表
};
其中struct關(guān)鍵字表示在構(gòu)造一個結(jié)構(gòu)體類型,結(jié)構(gòu)體名用來該結(jié)構(gòu)體這個類型的名稱,成員列表表示要描述的復(fù)雜數(shù)據(jù)中用到的具體的成員變量,成員列表的定義方式和普通變量的定義方式相同。例如下面定義一個student結(jié)構(gòu)體類型:
struct student
{
char name[20];
int sno;
int age;
char sex[10];
float score;
};
在studen這個結(jié)構(gòu)體中包含了姓名name、學(xué)號sno、年齡age;、性別sex[10];分?jǐn)?shù)score;這些數(shù)據(jù)類型該結(jié)構(gòu)體可以用來描述一個學(xué)生的基本信息。注意在結(jié)束一個結(jié)構(gòu)體的定義時要在右括號“}”后面加上一個括號。
上述只是結(jié)構(gòu)體的一種定義變量,還有其余兩中結(jié)構(gòu)體的定義方式:
1、
struct student
{
char name[20];
int sno;
int age;
char sex[10];
float score;
}s;
這里在定義結(jié)構(gòu)體的同時也定義了一個結(jié)構(gòu)體這種數(shù)據(jù)類型的變量s,這樣寫就可以直接使用該變量了。
2、
struct
{
char name[20];
int sno;
int age;
char sex[10];
float score;
}s;
這里在定義結(jié)構(gòu)體類型的同時也定義了變量,可以省略結(jié)構(gòu)體名,這種定義方式表示該結(jié)構(gòu)體類型只能使用一次。
結(jié)構(gòu)體的初始化
結(jié)構(gòu)體初始化:
結(jié)構(gòu)體的初始化也是采用初始化器去對結(jié)構(gòu)體進行初始化,
struct student s = { “tom”, 1, 18, “man”, 99 };
結(jié)構(gòu)體初始化的規(guī)則:
1、看每個成員變量,具體是什么數(shù)據(jù)類型。
2、根據(jù)各個成員變量自身的數(shù)據(jù)類型進行初始化。
3、初始化的順序要按照定義的順序依次進行初始化。
其實還可以在定義結(jié)構(gòu)體的同時定義變量然后進行初始化:
struct student
{
char name[20];
int sno;
int age;
char sex[10];
float score;
}s = { “tom”, 1, 18, “man”, 99 };
結(jié)構(gòu)體的成員變量引用的方式
結(jié)構(gòu)體的引用成員變量方式一共有兩種一個是通過結(jié)構(gòu)體變量名.成員名,另一個是結(jié)構(gòu)體指針->成員名,下面以一個例子來具體說明結(jié)構(gòu)體成員變量的引用方式;
#include <stdio.h>struct student
{char name[20];int age;char sex[10];float score;
};int main(int argc, const char *argv[])
{struct student s = { "tom", 18, "man", 90 };printf("name : %s\n", s.name);printf("age : %d\n", s.age);printf("sex : %s\n", s.sex);printf("score : %.2f\n", s.score);return 0;
}
上述代碼中定義了一個struct student的結(jié)構(gòu)體類型然后在main函數(shù)定義變量的同時進行了初始化,在打印結(jié)構(gòu)體的數(shù)據(jù)時采用了結(jié)構(gòu)體變量名.成員名的方式。
#include <stdio.h>
#include <stdlib.h>void outputStu(struct student *s, int len)
{int i = 0;for(i = 0; i < len; ++i){printf("name : %s\n", (s+i)->name);printf("Sno : %d\n", (s+i)->Sno);printf("age : %d\n", (s+i)->age);printf("sex : %s\n", (s+i)->sex);printf("score : %.2f\n", (s+i)->score);printf("\n");}
}int main(int argc, const char *argv[])
{struct student s[3] = { { "tom", 1, 18, "m", 99 }, { "jerry", 2, 18, "w", 90 }, { "lucy", 3, 18, "w", 92 } };outputStu(s, 3);return 0;
}
上述程序?qū)utputStu()函數(shù)的形參設(shè)置成結(jié)構(gòu)體指針去接收一個結(jié)構(gòu)體指針在打印結(jié)構(gòu)體成員變量時采用了結(jié)構(gòu)體指針->成員名的方式。
結(jié)構(gòu)體的大小
結(jié)構(gòu)體的大小遵循內(nèi)存對齊規(guī)則:
結(jié)構(gòu)體的對齊規(guī)則: //內(nèi)存地址的對齊
1.在32位的平臺上,默認(rèn)都是按4字節(jié)對齊的。
2.對于成員變量,
各自在自己的自然邊界上對齊。
char – 1字節(jié)
short – 2字節(jié)
int – 4字節(jié)
3.如果成員變量中有比4字節(jié)大。
此時整個結(jié)構(gòu)體按照4字節(jié)對齊。 //32位的平臺
4.如果成員變量中沒有有比4字節(jié)大。
此時整個結(jié)構(gòu)體按照最大的那個成員對齊。
注意在32位的平臺下:
//如果有超過4字節(jié) ,按照4字節(jié)對齊
//如果沒有超過4字節(jié)的,則按成員變量中最大對齊
在64位的平臺下:
//如果超過4字節(jié)的,按超過的最大的成員變量對齊
//如果沒有超過4字節(jié)的,則按成員變量中最大對齊
首先要知道的是系統(tǒng)讀取內(nèi)存當(dāng)中的數(shù)據(jù)時是4個字節(jié)4個字節(jié)地讀取的,這樣的讀取方式能提高數(shù)據(jù)的讀取效率和解析效率。
下面以一些例子來說明:
#include <stdio.h>struct s
{char a;short b;int c;
};int main(void)
{struct s aa;printf("sizeof(struct s) = %ld\n", sizeof(struct s));return 0;
}
我所用的平臺是64為的平臺所以下面也就主要說明64為平臺下的內(nèi)存對齊規(guī)則。在上述程序定義的結(jié)構(gòu)體的成員變量所占的字節(jié)總共是7個字節(jié),其中沒有超過4字節(jié)的,則按成員變量中最大對齊char a;占一個字節(jié)它可以放在能被1整除的地址編號的內(nèi)存當(dāng)中short b;占兩個字節(jié)放在a的后面且放在首地址編號能被2整除的內(nèi)存當(dāng)中,int c;占四個字節(jié)它放在首地址能被4整除的內(nèi)存空間當(dāng)中,最終整個結(jié)構(gòu)體也要對齊該結(jié)構(gòu)體沒有超過4字節(jié)的,則按成員變量中最大對齊也就是8個字節(jié)。
#include <stdio.h>struct s
{char a;//一字節(jié)double b;//八字節(jié)int c;//四字節(jié)
};int main(void)
{struct s aa;printf("sizeof(struct s) = %ld\n", sizeof(struct s));return 0;
}
在上述程序定義的結(jié)構(gòu)體的成員變量所占的字節(jié)總共是13個字節(jié),其中有超過4字節(jié)的double類型,char a;占一個字節(jié)它可以放在能被1整除的地址編號的內(nèi)存當(dāng)中double b;占八個字節(jié)放在a的后面且放在首地址編號能被8整除的內(nèi)存當(dāng)中,int c;占四個字節(jié)它放在首地址能被4整除的內(nèi)存空間當(dāng)中,最終整個結(jié)構(gòu)體也要對齊該結(jié)構(gòu)體有超過4字節(jié)的,則按成員變量中最大對齊也就是24個字節(jié)。
共用體
共用體的語法:
union 共用體名
{
成員變量;
};
語法定義例子:
union demo
{
char a;
short b;
int c;
};
共用體成員變量共用的是一塊內(nèi)存空間且公用的是最大成員的空間 。
在使用共用體時要注意:
1.共用體初始化時,只能給一個值,默認(rèn)時給到第一個成員的。
2.共用體變量中的值,取決與最后一次給到的值,還要看能影響幾個字節(jié)。
利用共用體判斷當(dāng)前操作系統(tǒng)是大端還是小端存儲:
#include <stdio.h>int isLittleEndian(void)
{union s{int a;char b;}c = { 1 };return c.b;
}int main(int argc, const char *argv[])
{printf("%d\n", isLittleEndian());return 0;
}
上述程序的共用體在初始化時給了一個1,一位int a;char b;共用的是同一塊空間它們對應(yīng)的首地址也是相同的,如果當(dāng)前系統(tǒng)為小端存儲那么1在存儲時低位數(shù)據(jù)就會存放在地址所以如果是小端存儲1就放在高位地址,則isLittleEndian()函數(shù)返回的是1反之就返回0。