### 結構體
* 結構體中的屬性長度會被自動補齊,這是為了方便指針位移運算
* 結構體中不能定義函數,可以定義函數指針
* 程序運行時,函數也是保存在內存中的,也有一個地址
* 結構體中只能定義變量
* 函數指針其實也是變量,它是指針變量
* 函數指針的定義 返回值類型(*變量名)(接收的參數);
* 函數指針的賦值: 函數指針只能指向跟它返回值和接收的參數相同的函數
代碼
```
#include<stdio.h>
#include<stdlib.h>
/**
c結構體 類似java的class struct來聲明c的結構體
結構體的大小大于等于結構體中每一變量的占字節數的和
結構體的大小是最大的那個變量所占字節數的整數倍,實際上是將不同類型的成員對齊后再相加
C結構體中不能定義函數,但是通過函數指針也可以解決問題,函數指針指向具體的函數,調用時通過結構體調用函數指針,就可以實現在結構體中擁有函數的需求
函數指針的定義 返回值(*函數指針變量名字)(返回值);
-> 間接引用運算符,指向結構體成員運算符,類似于結構成員運算符".";都是用來訪問結構體成員的,
只不過使用對象不同,用指針來訪問結構體成員,就要用"->";
假如使用結構體變量來訪問結構體成員,就需要結構體成員運算符"."
*/
void study(){
printf("good good study!\n");
}
typedef struct Student{
int age; //8
int score; // 4
char sex; //1
void(*studypointer)();//函數指針studypointer
} stud;//typedef為結構體取個別名stud它的作用和struct Student相同,也可以說是簡化為stud
main(){
stud stu = {18,100,'f'};
stu.studypointer = &study;
stu.studypointer();
struct Student* stuPointer = &stu;//結構體指針 struct Student* (類型后面加上“*”符號)
printf("*stuPointer.age = %d\n",(*stuPointer).age);
(*stuPointer).sex ='m';
printf("stu.sex = %c\n",stu.sex);
printf("stuPointer->age = %d\n",stuPointer->age);
//printf("stu.age = %hd\n",stu.age);
//printf("stu.score = %d\n",stu.score);
//printf("stu.sex = %c\n",stu.sex);
// printf("結構體student占%d個字節\n",sizeof(stu));
system("pause");
}
```
輸出結果
~~~
good good study!
*stuPointer.age = 18
stu.sex = m
stuPointer->age = 18
~~~
#### 零起點學通C語言摘要 ####
**結構體,顧名思義就是多個變量共用一塊內存,其實就是用戶自定義的數據類型,這個數據類型通常由多個類型的數據成員組成**
```
#include <stdio.h>
int main()
{
struct book //圖書 struct是關鍵字
{
int num; //編號
char name[20]; //書名
float price; //價格
int amount; //數量
};
return 0;
}
```
**結構變量**
struct book Jack ,struct是關鍵字,用來說明這是一個結構體類型,而book則說明該結構體類型的名字為book,Jack是通過book定義的結構變量,Jack必須通過點運算符訪問它的各個成員,然后利用它的成員來保存數據,“.”成為點運算符或者結構成員運算符,優先級高于賦值運算符
**結構變量的多種定義方式**
```
#include <stdio.h>
#include <string.h>
//一、先聲明結構體類型再定義變量。
//先聲明結構體類型:
struct employees //員工
{
char name[20]; //姓名
float pay; //工資
};
//再定義結構變量:
struct employees Jane;
//也可以一次性定義多個結構變量,每兩個結構變量之間用逗號隔開:
struct employees John,Rose,Mick;
//該語句一次性定義了3個結構變量--John、Rose和Mick。
int main()
{
//二、聲明結構體類型的同時定義變量。
struct employees_a //員工
{
char name[20]; //姓名
float pay; //工資
} Jame,Tom,Kity;
//右大括號的后面是定義的變量,可以定義一個,
//也可以定義多個,假如定義多個,用逗號將它們隔開。
//以下為結構變量賦值
strcpy(Jame.name,"Jack"); //姓名為Jack
Jame.pay=3278.60f; //工資為3278.60
strcpy(Tom.name,"Tom"); //姓名為Tom
Tom.pay=3578.60f; //工資為3578.60
strcpy(Kity.name,"Kity"); //姓名為Kity
Kity.pay=3978.60f; //工資為3978.60
//三、省略結構體類型的名稱。
/*
struct //員工
{
char name[20]; //姓名
float pay; //工資
}LiMing,Liu,Cheng;
//struct后面可省略掉結構體的名稱。
//以下為結構變量賦值
strcpy(LiMing.name,"Jack"); //姓名為LiMing
LiMing.pay=3278.60f; //工資為3278.60
strcpy(Liu.name,"Liu"); //姓名為Liu
Liu.pay=3578.60f; //工資為3578.60
strcpy(Cheng.name,"Cheng"); //姓名為Cheng
Cheng.pay=3978.60f; //工資為3978.60
*/
return 0;
}
```
**結構變量的初始化**
```
/*單行初始化
#include <stdio.h>
struct //員工
{
char name[20];//姓名
float pay; //工資
} one={"李磊",3452.86f},two={"趙安",4562.50f};//可以直接對這2個結構變量進行初始化
int main()
{
printf("%s的工資為:%.2f\n",one.name,one.pay);
printf("%s的工資為:%.2f\n",two.name,two.pay);
return 0;
}
*/
//分行初始化 結構變量很多,則需要給結構體類型取個名字,然后在定義結構變量的時候進行初始化
#include <stdio.h>
struct employees //員工
{
char name[20]; //姓名
float pay; //工資
};
int main()
{
struct employees LiLei={"李磊",3452.86f};//定義LiLei的時候進行初始化
struct employees ZhaoAn={"趙安",4562.50f};
printf("%s的工資為:%.2f\n",LiLei.name,LiLei.pay);
printf("%s的工資為:%.2f\n",ZhaoAn.name,ZhaoAn.pay);
return 0;
}
```
**結構變量的賦值**
```
#include <stdio.h>
struct employees //員工
{
char name[20]; //姓名
float pay; //工資
};
int main()
{
struct employees ZhaoAn={"李磊",3452.86f};
struct employees LiLei={"趙安",4562.50f};//初始化的時候出錯,數據保存ZhaoAn和LiLei的數據保存錯誤
struct employees three;//定義第三個結構體暴力,用于交換ZhaoAn和LiLei的值
three=ZhaoAn;
ZhaoAn=LiLei;
LiLei=three;
printf("%s的工資為:%.2f\n",ZhaoAn.name,ZhaoAn.pay);
printf("%s的工資為:%.2f\n",LiLei.name,LiLei.pay);
return 0;
}
```
**結構體數組**
由多個結構變量組成的數組叫做結構體數組
```
#include <stdio.h>
#define N 10
struct employees //員工
{
char name[20]; //姓名
float pay; //工資
};
int main()
{
struct employees em[N];//利用結構體類型employees定義一個結構體數組em,它有N個元素,每個元素都是一個結構體變量
int i;
for (i=0;i<N;i++)
{
printf("請輸入第%d名員工的姓名:",i+1);
scanf("%s",&em[i].name);//訪問結構體中的元素通過下標
printf("請輸入第%d名員工的工資:",i+1);
scanf("%f",&em[i].pay);
}
printf("列出所有員工的工資\n");
for (i=0;i<N;i++)
{
printf("%s的工資為:%.2f\n",em[i].name,em[i].pay);
}
return 0;
}
```
**結構體的嵌套**
一個結構體變量可以嵌套在另一個結構體中
```
#include <stdio.h>
struct date //日期
{
int year; //年
int month; //月
int day; //日
};
struct employees //員工
{
char name[20]; //姓名
float pay; //工資
struct date joinDate; //參加工作時間
};
int main()
{
struct employees em; //創建一個員工em
em.joinDate.year=1978; //該員工1978年參加工作
em.joinDate.month=12; //參加工作的月份是12
em.joinDate.day=30; //參加工作的日期是30
return 0;
}
```
**結構體的大小**
**對齊規則,結構體中最大成員的字節必須是其它成員的整數倍,假如不夠則補齊**
~~~
#include<stdio.h>
struct stu
{
int i;//4
char j;//1
float c;//4
};
struct stu1
{
char j;//1
int i;//4
double c;//8
};
struct stu2
{
char j;//1
int i;//4
double c;//8
char k;//1
};
struct stu3
{
char j;//1
int i;//4
double c;//8
char k;//1
char m;
char o;
char p;
char q;
char r;
char s;
char t;
};
struct stu4
{
char j;//1
int i;//4
double c;//8
char k;
char m;
char o;
char p;
char q;
char r;
char s;
char t;
char u;
};
int main()
{
struct stu s1={1,'c',198.12f};
int n=sizeof(s1);
printf("%d\n",n);//12
printf("%d\n",sizeof(struct stu1));//16
printf("%d\n",sizeof(struct stu2));//24
printf("%d\n",sizeof(struct stu3));//24
printf("%d\n",sizeof(struct stu4));//32
return 0;
}
~~~
輸出結果
~~~
12
16
24
24
32
~~~
- **struct stu 中int占用4個字節, char占用1個字節,float占用4個字節,將所有成員都對齊排放,將char與int對齊,這樣char也占用4個字節,float同樣占用4個字節,這樣總共就是12個字節**
- **struct stu1中int占用4個字節, char占用1個字節,double則占用8個字節,正好是前面2個成員的整數倍,因此第三個成員占用字節數保持8個不變,將char與int對齊,這樣char也占用4個字節,將3個成員所占字節數相加:4+4+8=16**
- **struct stu2中int占用4個字節, char占用1個字節,double則占用8個字節,因為第四個成員是char類型,占用1個字節,為了與第三個成員對齊,也給他分配8個字節,假如double后面有8個char型成員,則這8個char型成員將擠在一起。結構體大小為4+4+8+8=24**
- **struct stu3 中double后面有8個char型成員,則這8個char型成員將擠在一起,結構體大小為4+4+8+8=24**
- **struct stu4 中double后面有9個char型成員,前8個char擠在一起,合占8個字節,第九個char型成員,結構體大小補齊為8則,結構體大小是4+4+8+8+8=32**
#### 結構體與指針 ####
可以通過取地址符來獲取結構體變量的地址,然后將該地址交給指針來保存,那么只要指針的值不被修改,就可以找到結構體變量
#### 指向結構體變量的指針
```
#include<stdio.h>
#include<string.h>
struct book
{
char name[10];
float price;
};
int main()
{
struct book d1;
struct book *p;
p=&d1;//取出結構體變量1的地址賦給指針p,現在p指向結構體變量d1
strcpy(p->name,"呼嘯山莊");//調用strcpy函數,將"呼嘯山莊"復制到指向的結構體變量d1的成員ame中
p->price=11.80f;
printf("書名:%s\t價格:%.2f\n",p->name,p->price);
return 0;
}
```
#### 指向結構體數組的指針
一個指針保存了結構體數組的地址,就可稱為指向結構推為數組的指針
```
#include<stdio.h>
#include<string.h>
struct book
{
char name[10];
float price;
};
int main()
{
struct book mybook[3]={
{"呼嘯山莊",11.80f},
{"三國演義",46.50f},
{"百年孤獨",40.10f}
};
struct book *p;
int i;
p=mybook;
/**將結構體數組名復制給指針p,由于數組名即數組的地址,
而數組的地址又是該數組第一個元素的地址,即將第一個結構體變量的地址復制給了指針p
*/
for (i=0;i<3;i++)//數組mybook共保存了3個結構體變量,因此循環3次
{
printf("書名:%s\t價格:%.2f\n",p->name,p->price);
p++;
}
return 0;
}
```
>**指向結構體數組的指針每自加一次,是在原有地址的基礎上再加上一個元素(結構體變量)所占用的字節數,因此會指向下一個結構體變量**
- 前言
- JNI基礎知識
- C語言知識點總結
- ①基本語法
- ②數據類型
- 枚舉類型
- 自定義類型(類型定義)
- ③格式化輸入輸出
- printf函數
- scanf函數
- 編程規范
- ④變量和常量
- 局部變量和外部變量
- ⑤類型轉換
- ⑥運算符
- ⑦結構語句
- 1、分支結構(選擇語句)
- 2、循環結構
- 退出循環
- break語句
- continue語句
- goto語句
- ⑧函數
- 函數的定義和調用
- 參數
- 函數的返回值
- 遞歸函數
- 零起點學通C語言摘要
- 內部函數和外部函數
- 變量存儲類別
- ⑨數組
- 指針
- 結構體
- 聯合體(共用體)
- 預處理器
- 預處理器的工作原理
- 預處理指令
- 宏定義
- 簡單的宏
- 帶參數的宏
- 預定義宏
- 文件包含
- 條件編譯
- 內存中的數據
- C語言讀文件和寫文件
- JNI知識點總結
- 前情回顧
- JNI規范
- jni開發
- jni開發中常見的錯誤
- JNI實戰演練
- C++(CPP)在Android開發中的應用
- 掘金網友總結的音視頻開發知識
- 音視頻學習一、C 語言入門
- 1.程序結構
- 2. 基本語法
- 3. 數據類型
- 4. 變量
- 5. 常量
- 6. 存儲類型關鍵字
- 7. 運算符
- 8. 判斷
- 9. 循環
- 10. 函數
- 11. 作用域規則
- 12. 數組
- 13. 枚舉
- 14. 指針
- 15. 函數指針與回調函數
- 16. 字符串
- 17. 結構體
- 18. 共用體
- 19. typedef
- 20. 輸入 & 輸出
- 21.文件讀寫
- 22. 預處理器
- 23.頭文件
- 24. 強制類型轉換
- 25. 錯誤處理
- 26. 遞歸
- 27. 可變參數
- 28. 內存管理
- 29. 命令行參數
- 總結
- 音視頻學習二 、C++ 語言入門
- 1. 基本語法
- 2. C++ 關鍵字
- 3. 數據類型
- 4. 變量類型
- 5. 變量作用域
- 6. 常量
- 7. 修飾符類型
- 8. 存儲類
- 9. 運算符
- 10. 循環
- 11. 判斷
- 12. 函數
- 13. 數學運算
- 14. 數組
- 15. 字符串
- 16. 指針
- 17. 引用
- 18. 日期 & 時間
- 19. 輸入輸出
- 20. 數據結構
- 21. 類 & 對象
- 22. 繼承
- 23. 重載運算符和重載函數
- 24. 多態
- 25. 數據封裝
- 26. 接口(抽象類)
- 27. 文件和流
- 28. 異常處理
- 29. 動態內存
- 30. 命名空間
- 31. 預處理器
- 32. 多線程
- 總結
- 音視頻學習 (三) JNI 從入門到掌握
- 音視頻學習 (四) 交叉編譯動態庫、靜態庫的入門學習
- 音視頻學習 (五) Shell 腳本入門
- 音視頻學習 (六) 一鍵編譯 32/64 位 FFmpeg 4.2.2
- 音視頻學習 (七) 掌握音頻基礎知識并使用 AudioTrack、OpenSL ES 渲染 PCM 數據
- 音視頻學習 (八) 掌握視頻基礎知識并使用 OpenGL ES 2.0 渲染 YUV 數據
- 音視頻學習 (九) 從 0 ~ 1 開發一款 Android 端播放器(支持多協議網絡拉流/本地文件)
- 音視頻學習 (十) 基于 Nginx 搭建(rtmp、http)直播服務器
- 音視頻學習 (十一) Android 端實現 rtmp 推流
- 音視頻學習 (十二) 基于 FFmpeg + OpenSLES 實現音頻萬能播放器
- 音視頻學習 (十三) Android 中通過 FFmpeg 命令對音視頻編輯處理(已開源)