我決定了要成為海賊王便要為此而戰,我必須變的更強。———路飛
階段1目标:
基本了解C語言文法,站在全局,避去晦澀難懂,鮮明梳理C語言基本概念,為算法競賽等計算機專業比賽鋪好道路。傳統功夫講究點到為止,此階段僅點明文法知識,後續階段再進一步精進學習。
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIiNx8FesU2cfdGLwczX0xiRGZkRGZ0Xy9GbvNGLwIzXlpXazxSUyEWNZ1Wc1EXaMVTQpxUNENkW14UYZVTQClGVF5UMR9Fd4VGdsATNfd3bkFGazxycykFaKdkYzZUbapXNXlleSdVY2pESa9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnLwMzMzADM0ATMyATOwEjMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
目錄
1.本章重點
2.結構體的聲明
2.1結構的基礎知識
2.2結構體的聲明
2.3結構成員的類型
3.結構體變量的定義和初始化
3.1結構體變量的定義
3.2結構體變量的初始化
4.結構體成員的通路
5.結構體傳參
1.本章重點
結構體類型的聲明
結構體初始化
結構體成員通路
結構體傳參
2.結構體的聲明
2.1結構的基礎知識
結構是一些值的集合,這些值稱為成員變量。結構的每個成員可以是不同類型的變量。
比如說:人,或者書📕是一個複雜對象,屬性不止一個,是以就構成了成員變量。
//定義一本書
struct Book
{
char name[20];
char autor[20];
float price;
};
//定義一個坐标
struct Point
{
int x;
int y;
};
注意:
這些都是結構體類型,并沒有建立變量,是以沒有占用空間。
2.2結構體的聲明
struct tag //struct 名字
{
member - list;//成員變量清單
}variable - list;//結構體類型建立的變量
注意:( struct不可省略,名字允許省略 )
- struct關鍵字不能省略。因為struct是結構體類型關鍵字。
- 結構體類型名是自定義的合法辨別符,說明該結構體類型獨有的名字。當結構體類型名預設時,為無名結構體。是以說明結構體類型名可以預設,但是關鍵字struct不可以。
我們看着貌似和剛剛我們建立的書📕和坐标這種結構體定義有所不同,即:在最後的分号之前多了個東西,那是什麼意思呢?
我們來對比思考一下,其實啊,這兩種寫法本質上是一樣的,隻不過一個是全局變量,一個是局部變量。
//定義一本書
struct Book
{
char name[20];
char autor[20];
float price;
};
int main()
{
struct Book b1;//結構體類型struct Book建立的局部變量b1
struct Book b2;//結構體類型struct Book建立的局部變量b2
}
//定義一本書
struct Book
{
char name[20];
char autor[20];
float price;
}b1, b2; //結構體類型struct Book建立的全局變量
int main()
{
}
兩種寫法都可以,不過是一個局部變量一個全局變量,一個放在記憶體的棧區一個放在記憶體的靜态區罷了。
比如說我們用結構體定義聲明一個學生,我們可以這樣寫:
struct Stu
{
char name[20];
int age;
char id[20];
};
int main()
{
struct Stu a;//定義一個學生a
return 0;
}
我們有時候在main()函數中嫌struct Stu結構體類型來定義變量,過于備援,一般會用重命名的方式再來把struct Stu這個結構體類型重新命名一下,比如:
typedef struct Stu
{
char name[20];
int age;
char id[20];
}Stu;
int main()
{
Stu a;
return 0;
}
注意:
此處新定義的Stu不是變量哈,和剛剛的全局變量不一樣喲~,此處新定義的Stu仍然是結構體類型struct Stu,隻不過我們覺得備援換了種寫法,用typedef來重命名一下罷了~~
2.3結構成員的類型
結構的成員可以是标量、數組、指針,甚至是其他結構體。
3.結構體變量的定義和初始化
有了結構體類型,那如何定義結構體變量?其實很簡單。
3.1結構體變量的定義
struct Point
{
int x;
int y;
}p1; //聲明類型的同時定義變量p1
struct Point p2; //定義結構體變量p2
3.2結構體變量的初始化
struct Point
{
int x;
int y;
}p1; //聲明類型的同時定義變量p1
struct Point p2; //定義結構體變量p2
//初始化:定義變量的同時賦初值。
struct Point p3 = { x, y };
注意:結構體變量初始化,賦的初值是與結構體中的類型順序相對應,且類型對應的。
那如果我們結構體中又嵌套一個結構體呢?改如何賦予初值??
struct S
{
int a;
char c;
double d;
};
struct T
{
struct S s;
char name[20];
int num;
};
int main()
{
struct T t = { {2,'100',3.14},"張三",6 };
return 0;
}
4.結構體成員的通路
結構變量的成員是通過點操作符(.)通路的。 點操作符接受兩個操作數。
struct S
{
int a;
char c;
double d;
};
struct T
{
struct S s;
char name[20];
int num;
};
int main()
{
struct T t = { {2,'m',3.14},"張三",666 };
printf("%d % c %f %s %d", t.s.a, t.s.c, t.s.d, t.name, t.num);
return 0;
}
注意:
t的成員變量中含有struct S s這個結構體,中間仍然需要(.)先來通路t中的s,然後再用(.)來通路s中的成員變量。
在我的部落格 05操作符和表達式 這一章節中,我們知道用位址同樣可以通路成員變量,我們再來看一下叭~:
struct S
{
int a;
char c;
double d;
};
struct T
{
struct S s;
char name[20];
int num;
};
int main()
{
struct T t = { {2,'m',3.14},"張三",666 };
printf("%d % c %f %s %d\n", t.s.a, t.s.c, t.s.d, t.name, t.num);
struct T* pt = &t;
printf("%d % c %f %s %d\n", pt->s.a, pt->s.c, pt->s.d, pt->name, pt->num);
return 0;
}
在結構體通路成員變量中,我們需要注意:
- 如果我們是想通過位址來通路結構體中的成員,需要 ->
- 如果我們是想通過變量來通路結構體中的成員,需要 .
5.結構體傳參
struct S
{
int a[100];
int num;
char ch;
double d;
};
void Print1(struct S ss)
{
printf("%d %d %d %d %d %c %lf", ss.a[0], ss.a[1], ss.a[2], ss.a[3], ss.num, ss.ch, ss.d);
}
int main()
{
struct S s = { {1,2,3,4,5,6},100,'w',3.14 };
Print1(s);
return 0;
}
我們看到,傳參的時候,此時是值傳遞,即:将我們的結構體變量s,原封不動的copy一份,來實作列印,其實是非常浪費空間的。那麼我們可以用位址來傳遞。
struct S
{
int a[100];
int num;
char ch;
double d;
};
void Print2(struct S* ss)
{
printf("%d %d %d %d %d %c %lf", ss->a[0], ss->a[1], ss->a[2], ss->a[3], ss->num, ss->ch, ss->d);
}
int main()
{
struct S s = { {1,2,3,4,5,6},100,'w',3.14 };
Print2(&s);
return 0;
}
上面的 Print1 和 Print2 函數哪個好些?
答案是:首選Print2函數
函數傳參的時候,參數是需要壓棧的。 如果傳遞一個結構體對象的時候,結構體過大,參數壓棧的的系統開銷比較大,是以會導緻性能的下降。
舉個好了解的栗子:
int Add(int x, int y)
{
int z = x + y;
return z;
}
int main()
{
int a = 10;
int b = 20;
int c = 0;
c = Add(a, b);
printf("%d", c);
return 0;
}
總結:
結構體傳參的時候,要傳結構體的位址。