C語言-->(十四)結構體、巨集、編譯

林堯彬發表於2020-04-04

知識點:
1.結構體 struct
2.typedef關鍵字
3.巨集的定義
4.巨集與函式的區別
5.檔案包含和多檔案編譯
6.條件編譯
===========================
結構體
思考:如果現在希望儲存一個學生的資訊,姓名,身高,年齡,地址,該如何儲存

char name[64];
float height;
int age;
char addr[64];


1.什麼是結構體 struct
結構體指的是一種資料結構,是c語言中複合資料型別的一
種多種不同資料型別的集合

2.結構體的作用
結構體可以用來建立複雜的資料結構

3.結構體的定義

1)定義的語法
struct 結構體名

成員列表
};


4.結構體成員宣告
1)可以宣告各種型別的成員
2)成員宣告時需要注意的地方
練習:

1.定義一個結構體,用來描述時間,
具體說該結構體有三個成員,分別描述時分秒資訊
//1構造一個時間型別
//2把當前時間存到時間變數
//3顯示時間變數

2.定義一個結構體,用來描述書本的資訊,
結構體成員包括 名稱,單價,作者,出版社,出版日期

 

5.宣告結構體型別變數和初始化 //"C programe",38.8,"譚浩強","清華"
(1)方法一
(2)方法二
6.結構體成員的訪問方式
結構體變數名.成員名

練習:
1.初始化並輸出時間結構體的資訊
2.初始化並輸出書本結構體的資訊
3.從終端輸入書本的資訊,並且輸出


7.結構體陣列
資料型別 陣列名 陣列長度

練習:
1.建立包含2個學生資訊的登記表,其中包括學號,姓名,性別,住址和3門成績 c cpp OC

8.結構體指標 ->


9.結構體的大小和記憶體對齊
1)思考:為什麼會出現相同機構體,大小不同的情況
2)原因:大致可以分為2點
在用sizeof運算子求算某結構體所佔空間時,並不是簡單地將結構體中所有元素各自佔的空間相加,這裡涉及到記憶體位元組對齊的問題。
從理論上講,對於任何 變數的訪問都可以從任何地址開始訪問,
但是事實上不是如此,實際上訪問特定型別的變數只能在特定的地址訪問,
這就需要各個變數在空間上按一定的規則排列, 而不是簡單地順序排列,這就是記憶體對齊。

記憶體對齊的原因:

1)某些平臺只能在特定的地址處訪問特定型別的資料;
2)提高存取資料的速度。比如有的平臺每次都是從偶地址處讀取資料,對於一個int型的變數,若從偶地址單元處存放,則只需一個讀取週期即可讀取該變數;但是若從奇地址單元處存放,則需要2個讀取週期讀取該變數。
3)對齊方式
1>和編譯器有關,一般32位系統預設以4個位元組方式對齊
2>本系統以結構體中最大元素的型別進行對齊

==========================================================================
typedef關鍵

思考:程式的跨平臺性 64 32 16 8
int int int2
long long long

size_t

long long int64

 


1.typedef作用
1)typedef常用來定義一個識別符號和及關鍵字的別名,並不分配實際的記憶體
2)typedef可以增強程式的可讀性
3)typedef可以增強識別符號的靈活性
2.typedef本質
typedef本質為型別的別名
3.typedef語法使用
typedef 已有型別名 新型別名;

4.重定義結構體
5.重定義型別
6.typedef與define的區別
1)typedef是為了程式的可讀性而為識別符號另起的別名,而
define在c語言中是為了定義常量,常用程式碼替換
2)define可以使用#ifdef和#ifndef來進行邏輯判斷


==========================================================================
巨集定義
0.什麼是巨集定義
1)巨集定義是C提供的三種預處理功能中的一種,預處理包括巨集定義、檔案包含、條件編譯
1.巨集定義的作用
1)使用識別符號來替換一些常用的程式碼

WALK 小明---nickname 別名
2.巨集定義的本質
1)一種佔位符,用來代替一些常用程式碼
2)一切以轉換為前提,做任何事情之前先要替換
2.基本的巨集定義
0)#define指令語法
巨集指令 巨集名 巨集體
1)識別符號
2)大寫,不加分號結束
3)使用
示例:定義常量PI的巨集
練習:
定義陣列大小的巨集
定義重力加速度巨集 9.8

3.帶有引數的巨集定義
1)示例:計算兩數最大值的巨集
練習:
1.計算兩數之和的巨集,兩數之積


思考:ADD(1,2)*ADD(1,2)結果



4.巨集替換的問題
1)巨集替換作用的演示,gcc編譯引數
2)思考:能否巢狀定義或呼叫


5.巨集和函式的區別

1 )巨集會在編譯器在對原始碼進行編譯的時候進行簡單替換,不會進行任何邏輯檢測,即簡單程式碼複製而已。
2)巨集進行定義時不會考慮引數的型別。
3)引數巨集的使用會使具有同一作用的程式碼塊在目標檔案中存在多個副本,即會增長目標檔案的大小。
4)引數巨集的執行速度會比函式快,因為不需要引數壓棧/出棧操作。
5)引數巨集在定義時要多加小心,多加括號。
6)函式只在目標檔案中存在一處,比較節省程式空間。
7)函式的呼叫會牽扯到引數的傳遞,壓棧/出棧操作,速度相對較慢。
8)函式的引數存在傳值和傳地址(指標)的問題,引數巨集不存在。
==================================
檔案包含和多檔案編譯
1.思考:如何實現多人合作專案
介面---->函式原型 .h //head
實現---->函式定義 .c

cvs git svn

2.回憶函式定義和宣告
3.標頭檔案和原始檔
4.#include指令語法!!!!
1)本質:標頭檔案包含實際是替換檔案內容
2)作用:實現宣告和實現相分離,進一步使程式更加的模組化

#include <stdio.h> 尖括號表示系統標準目錄
雙引號表示自定義路徑
add, sub, mut, div + -
5.示例:連結串列的實現的宣告相分離
練習:
1.實現加減乘除四則運算,並將函式的宣告與實現相分離
並編寫測試函式測試該些函式

A B C D 200 100


==========================================================================
條件預編譯
需求:現在使用者只購買系統中的某些模組
1.思考:如何可以簡單快速的在編譯的過程中滿足使用者的需求

2.#ifdef 條件編譯語法
#ifdef 標示符
程式段1
#else
程式段2
#endif

 


#ifndef
1)作用:模組選擇
示例:判斷是否定義過PI巨集
練習:判斷是否有定義上述的常用巨集
思考:
1.如何可以安全,快速的註釋程式碼
2.// 和 /* */註釋是否可以巢狀使用

3.#if 條件編譯語法
#if 表示式
程式段1
#else
程式段2
#endif

1)作用
快速安全的註釋程式碼
4.安全註釋
思考:如果重複包含標頭檔案會如何
5.防止標頭檔案重複包含
#ifndef TEST_H_H標頭檔案名
#define TEST_H_H

#include "test.h"
#endif

==========================================================================
除錯巨集

思考:如何使用printf除錯程式碼,是否方便移出
1.除錯巨集定義
INFO, WARN, ERROR, DEBUG
2.除錯開關
3.預定義巨集
printf("line = %d, file = %s, DATA = %s, TIME = %s",
__LINE__, __FILE__, __DATE__, __TIME__);
__LINE__:行號
__FILE__:檔名
__DATE__:日期 %s
__TIME__:時間
__func__:函式名

==========================================================================

 

轉載於:https://www.cnblogs.com/iOSteemo/p/4304487.html

相關文章