文章目錄
- 1.結構體型別的宣告
- 2.結構體變數的定義和初始化
- 3.結構體記憶體對齊
- 4.結構體傳參
1.結構體型別的宣告
結構的基礎知識
結構是一些值的集合,這些值稱為成員變數,結構的每個成員可以是不同型別的變數,
結構的宣告 :
struct tag
{
member-list;
}variable-list;
例如描述一個學生 :
struct Stu
{
char name[20];//名字
int age;//年齡
char sex[5];//性別
char id[20];//學號
}stu1,stu2;//分號不能丟
特殊的宣告 :
在宣告結構的時候,可以不完全的宣告,
//匿名結構體型別
struct
{
int a;
char b;
float c;
}x;
struct
{
int a;
char b;
float c;
}a[20], *p;
上面的兩個結構在宣告的時候省略掉了結構體標簽(tag),也叫匿名結構體型別
匿名結構體型別因為沒有名字,因此創建結構體變數時只能在 variable-list 中創建
那么問題來了
// 在上面的基礎上,這種代碼合理嗎?
p = &x;
可能有讀者覺得這兩個結構體的成員串列都一樣,是同一型別,那這句代碼就沒有錯
其實不然
警告: 編譯器會把上面的兩個宣告當成完全不同的兩個型別, 所以是非法的,
2.結構體變數的定義和初始化
struct Point
{
int x;
int y;
}p1; //宣告型別的同時定義變數p1
struct Point p2; //定義結構體變數p2
//初始化:定義變數的同時賦初值,
struct Point p3 = {x, y};
struct Stu //型別宣告
{
char name[15];//名字
int age; //年齡
};
struct Stu s = {"zhangsan", 20};//初始化
struct Node
{
int data;
struct Point p;
struct Node* next;
}n1 = {10, {4,5}, NULL}; //結構體嵌套初始化
struct Node n2 = {20, {5, 6}, NULL};//結構體嵌套初始化
3.結構體記憶體對齊
首先得掌握結構體的對齊規則:
(1). 第一個成員在與結構體變數偏移量為0的地址處,
(2). 其他成員變數要對齊到某個數字(對齊數)的整數倍的地址處,
對齊數 = 編譯器默認的一個對齊數 與 該成員大小的較小值,
VS默認的值為8
Linux默認的值為4
(3). 結構體總大小為最大對齊數(每個成員變數都有一個對齊數)的整數倍,
(4). 如果嵌套了結構體的情況,嵌套的結構體對齊到自己的最大對齊數的整數倍處,結構體的整體大小就是所有最大對齊數(含嵌套結構體的對齊數)的整數倍,
僅僅看規則是蒼白無力的,下面我們配合題目來進行講解
(1).
struct S1
{
char c1;
int i;
char c2;
};
printf("%d\n", sizeof(struct S1));

(2).
struct S2
{
char c1;
char c2;
int i;
};
printf("%d\n", sizeof(struct S2));

(3).
struct S3
{
double d;
char c;
int i;
};
printf("%d\n", sizeof(struct S3));

(4).結構體嵌套問題
struct S4
{
char c1;
struct S2 s2;
double d;
};
printf("%d\n", sizeof(struct S4));

由此可知在設計結構體的時候,我們既要滿足對齊,又要節省空間,如何做到呢 ?
我們可以看到 : struct S1 和 struct S2 雖然成員變數型別一樣,但一個是 12個位元組,一個是 8個位元組
struct S1
{
char c1;
int i;
char c2;
};
struct S2
{
char c1;
char c2;
int i;
};
所以 讓占用空間小的成員盡量集中到一起
當然我們也可以修改默認對齊數
之前我們見過了 #pragma 這個預處理指令,這里我們再次使用,可以改變我們的默認對齊數,
#include <stdio.h>
#pragma pack(8)//設定默認對齊數為8
struct S1
{
char c1;
int i;
char c2;
};
#pragma pack()//取消設定的默認對齊數,還原為默認
#pragma pack(1)//設定默認對齊數為1
struct S2
{
char c1;
int i;
char c2;
};
#pragma pack()//取消設定的默認對齊數,還原為默認
int main()
{
//輸出的結果是什么?
printf("%d\n", sizeof(struct S1));
printf("%d\n", sizeof(struct S2));
return 0;
}
輸出結果為 12 和 6,大家可以自己去嘗試畫圖驗證
結論:
結構在對齊方式不合適的時候,我么可以自己更改默認對齊數,
4.結構體傳參
struct S
{
int data[1000];
int num;
};
struct S s = {{1,2,3,4}, 1000};
//結構體傳參
void print1(struct S s)
{
printf("%d\n", s.num);
}
//結構體地址傳參
void print2(struct S* ps)
{
printf("%d\n", ps->num);
}
int main()
{
print1(s); //傳結構體
print2(&s); //傳地址
return 0;
}
上面的 print1 和 print2 函式哪個好些?
選擇print2函式
因為函式傳參的時候,引數是需要壓堆疊,會有時間和空間上的系統開銷,
如果傳遞一個結構體物件的時候,結構體過大,引數壓堆疊的的系統開銷比較大,導致性能下降
關于函式呼叫可以去看這篇文章
淺析函式的呼叫程序
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/266326.html
標籤:AI
上一篇:智能車AI電磁部署學習 (二)
