程式設計有時候可以利用自動化大大節省事情的處理時間,但有時候如果對於語言的不熟悉,可能會造成程式碼不如預期,而這件事常常出現在 C 語言的預處理部分!
Photo by @nathangbingle on Unsplash
在 C 語言中有所謂的前 4 步驟,詳閱 C preprocessor: Phases - wiki
在開始之前,請你回答,註解(comment),是不是預處理要處理的項目之一?答案是: 是的,是預處理的項目。
我們將從 3 個方面切入:
是的沒錯, Swift 也有預處理的環節。分別如下:
import
,透過這個指令,我們可以使用 其他 module 的程式碼。#if (MYFLAG && DEBUG)
,在 Swift 的編譯指令 swift build -Xswiftc "-DMYFLAG" -Xswiftc "-DDEBUG"
加入自己的編譯變數。#if canImport(MODULE)
、#if os(OSNAME)
、#if arch(ARCH
針對作業系統的設定編譯@available(iOS 13, *)
與 if #available(iOS 13, *)
,針對 OS版本的條件編譯#filepath
、#function
、#line
、typealias
以上是我濃縮的 Swift preprocessor,主要希望可以引起讀者回憶,因此相對簡略很多。
在 C 語言與 Objective-C 使用的預處理幾乎是一模一樣的,同樣的,我們從三個面向處理:
引用檔案:#include
早在系列開始的前期 #include <HEADER.h>
,一直圍繞在 C 語言的範例中,詳細可以看第 9 天的文章,值得提醒的是 Objective-C 在檔案引用多了 #import
與 @import
,還有在後續的Objective-C 物件導向會提到 @class
條件編譯: #ifdef
與 #ifndef
在上一個文章中,我們有提到 Include guard
,就是使用了條件編譯。而且由於 Swift 在預處理部分絕大多數承襲了 Objective-C,因此在 Flag 的定義也是如此。
// C
#define DEBUG 1
#if DEBUG
log(_SOMETHING_TO_LOG_);
#endif
OS版本的檢查也與 Swift 相似
// Objective-C
if (@available(macOS 20, *)) {
printf("macOS above 20\n");
}
這應該是最難懂的部分了。
首先,我們可以先從 Swift 相似的 #filepath
、#function
、#line
開始,C 語言已經有支援,Objective-C 可以使用。
巨集 | 解釋 |
---|---|
__DATE__ |
目前的日期字串,固定格式為 "MMM DD YYYY" |
__TIME__ |
目前的時間字串,固定格式為 "HH:MM:SS" |
__FILE__ |
當前行所在的 source code 檔案名稱 |
__LINE__ |
當前行所在的 source code 行數,以十進位表示 |
__OBJC__ |
當前編譯是否有採用 -objC |
更多預先定義到了巨集可以參考 Clang Language Extensions — Clang 12 documentation
在 C 語言中,自定義巨集基本上就是沒有邏輯的文字代換,也就是說可以將向替換的文字替換成自定義文字,請參考下面的 main.c
:
// C
#define NUMBER int
#define BEGIN {
#define END }
#define EXIT_SUCCESS 0
NUMBER main()
BEGIN
return EXIT_SUCCESS;
END
相信讀者可以感受到一絲絲苦難了,如果沒有可以嘗試看看 這個 GitHub 專案,找找看 e.c
檔案。
但是 #define
用的好,有時候會大大幫助開發時間,這部分在歷屆的鐵人賽已經有針對 C 語言的介紹,很實用。
在 Objective-C 有所謂的強調型別,透過 objc.h
的定義,可以看到很特別的處理。
這部分我推薦 bool 與 BOOL · KKBOX iOS_Mac OS X 基本開發教材,該文說明十分清楚。
// Objective-C
/* objc.h */
#define YES __objc_yes
#define NO __objc_no
...
# define Nil __DARWIN_NULL
...
# define nil __DARWIN_NULL
...
建議讀者打開電腦查找
objc.h
, 自己瀏覽一遍。
#define square(x) x * x
會造成什麼問題io.ccc
與 preprocessor 有關的得獎程式,嘗試分享你看懂多少。