前處理指令可以要求前處理器 (preprocessor) 在程式編譯之前,先進行加入其它檔案的內容、文字取代以及選擇性編譯等工作。

Slides:



Advertisements
Similar presentations
C++语言程序设计教程 第5章 构造数据类型 第6章 C++程序的结构.
Advertisements

第 2 章 初探 C++.
第九讲 类与对象 (I)面向对象基础.
第4章 数组 数组是由一定数目的同类元素顺序排列而成的结构类型数据 一个数组在内存占有一片连续的存储区域 数组名是存储空间的首地址
第八章 类和对象.
C++程序设计 王希 图书馆三楼办公室.
struct 可以在同一個名稱下擁有多種資料型態。使用struct能讓資料的存取和處理更為靈活。
C++语言程序设计 第四章 类与对象 成都信息工程学院计算机系.
函數(一) 自訂函數、遞迴函數 綠園.
Chap 18 類別與物件 夫有土者,有大物也。有大物者,不可以物。 物而不物,故能物物。 明乎物物者之非物也,豈獨治天下百姓而已哉!
第4章 函数与预处理 4.1 概述 4.2 定义函数的一般形式 4.3 函数参数和函数的值 4.4 函数的调用 *4.5 内置函数
教材 《C++程序设计》.谭浩强. 清华大学出版社 王雪晶
Scope & Lifetime 前言 Local Scope Global Functions & Objects
刘胥影 东南大学计算机学院 面向对象程序设计1 2010~2011第3学期 刘胥影 东南大学计算机学院.
C++语言程序设计 C++语言程序设计 第六章 指针和引用 第十一组 C++语言程序设计.
刘胥影 东南大学计算机学院 面向对象程序设计1 2011~2012第3学期 刘胥影 东南大学计算机学院.
Classes: A Deeper Look, Part 1
第一章 程序的基本结构. 第一章 程序的基本结构 教材及授课结构 本章目标 基本内容 扩展阅读 上机指导 应用举例 习题.
刘胥影 东南大学计算机学院 面向对象程序设计1 2010~2011第3学期 刘胥影 东南大学计算机学院.
C++语言程序设计 C++语言程序设计 第四章 数组及自定义数据类型 C++语言程序设计.
授课老师:龚涛 信息科学与技术学院 2018年3月 教材: 《Visual C++程序员成长攻略》 《C++ Builder程序员成长攻略》
Object-Oriented Programming in C++ 第一章 C++的初步知识
第 6 章 函式.
2 C++ 的基本語法和使用環境 親自撰寫和執行程式是學好程式語言的不二法門。本章藉由兩個簡單的程式,介紹C++ 程式的基本結構和開發環境,讓初學者能逐漸建立使用C++ 的信心。
程序设计专题一 结构化程序设计与递归函数 主讲教师: 刘新国.
第3章 變數、常數與資料型態 3-1 C語言的識別字 3-2 變數的宣告與初值 3-3 指定敘述 3-4 C語言的資料型態
第7章 编译预处理 本章要求: 本章重点: 本章难点: 掌握用#define定义无参数宏和带有参数宏定义和调用方法;
计算机网络讲义 第5章 批量数据处理—数组 一维数组 排序和查找 二维数组 字符串.
第3讲 C++程序控制结构 3.1 顺序结构 3.2 分支结构 3.3 循环结构 3.4 转向控制 3.5 综合案例分析.
C++程序设计 string(字符串类) vector(容器类).
C++大学基础教程 第4章 函数 北京科技大学 信息基础科学系.
程序的三种基本结构 if条件分支语句 switch多路开关语句 循环语句 循环嵌套 break,continue和goto语句
3 數學運算 3.1 鍵盤輸入 輸入函數cin 多重輸入cin 輸出格式化 3-3
谭浩强 编著 中国高等院校计算机基础教育课程体系规划教材 C++程序设计.
C++语言程序设计 第十一章 流类库与输入/输出.
C++语言程序设计 C++语言程序设计 第六章 指针和引用 第十一组 C++语言程序设计.
切換Dev c++顯示語言 工具->環境選項(V)->介面->language (Chinese TW)
授课老师:龚涛 信息科学与技术学院 2016年3月 教材:《Visual C++程序员成长攻略》 《C++ Builder程序员成长攻略》
第6章 预 处 理.
第九章 预处理命令.
序及第0章.
C++ 程式設計 基礎篇 張啟中 Chang Chi-Chung.
第14章 输入输出与文件 输入输出是指程序与外部设备交换信息 C++把输入输出看成是一个数据流 输入流:外围设备流向内存的数据
C++大学基础教程 第11章 多态性 北京科技大学 信息基础科学系 2019/4/8 北京科技大学.
第二章 基本数据类型及运算 C数据类型概述 基本数据类型 运算符和表达式 混合运算与类型转换 数据的输入输出 顺序程序设计举例.
Chapter 2 & Chapter 3.
C++语言程序设计 C++语言程序设计 第五章 函数 第十一组 C++语言程序设计.
C++语言程序设计 C++语言程序设计 第九章 类的特殊成员 第十一组 C++语言程序设计.
C++语言程序设计 C++语言程序设计 第三章 控制语句 第十一组 C++语言程序设计.
Oop8 function函式.
物件導向程式設計 CH2.
第11章 從C到C++語言 11-1 C++語言的基礎 11-2 C++語言的資料型態與運算子 11-3 C++語言的輸出與輸入
C++语言程序设计教程 第2章 数据类型与表达式 第2章 数据类型与表达式 制作人:杨进才 沈显君.
C++程式設計入門 變數與運算子 作者:黃建庭.
第6章 预 处 理.
第二讲 基本数据类 型及数组等 此为封面页,需列出课程编码、课程名称和课程开发室名称。
C/C++基礎程式設計班 C++: 物件的使用、參考、重載函式 講師:林業峻 CSIE, NTU 3/28, 2015.
第 3 章 类的基础部分 陈哲 副教授 南京航空航天大学 计算机科学与技术学院.
挑戰C++程式語言 ──第9章 函數.
#include <iostream.h>
C++语言程序设计 C++语言程序设计 第二章 基本数据类型与表达式 第十一组 C++语言程序设计.
C++语言程序设计 第十章 C++标准模板库 成都信息工程学院计算机系.
C++语言程序设计 C++语言程序设计 第十章 多态 第十一组 C++语言程序设计.
C++语言程序设计 C++语言程序设计 第九章 类的特殊成员 第十一组 C++语言程序设计.
《数据结构与算法设计》第一部分 面向对象的C++程序设计基础.
C++程序设计 概述 潘荣江 山东大学软件学院.
第18讲 从C到C++ 计算机与通信工程学院.
C++语言程序设计 C++语言程序设计 第十一章 异常处理 C++语言程序设计.
變數與資料型態  綠園.
C++语言程序设计 C++语言程序设计 第二章 基本数据类型与表达式 第十一组 C++语言程序设计.
Presentation transcript:

前處理指令可以要求前處理器 (preprocessor) 在程式編譯之前,先進行加入其它檔案的內容、文字取代以及選擇性編譯等工作。 Chap 11 前處理指令 前處理指令可以要求前處理器 (preprocessor) 在程式編譯之前,先進行加入其它檔案的內容、文字取代以及選擇性編譯等工作。

前處理指令 11.1 前處理器 11.2 使用 #define進行文字取代 11.3 使用 #define設定巨集指令 11.4 條件式編譯 11.5 其他與編譯器有關的前處理指令

前處理指令 #include 前處理指令不是C++ 敘述,不用分號「;」做結尾。例如: #include <iomanip> 與 #include 配合的檔案名稱有兩種語法。 例如: #include “Commom.h” 附錄 C中列出了C++ 標準程式庫裏面常用的標檔。 可以將檔案的詳細路徑寫在雙引號內。 例如: #include “c:\C++Test\Commom.h”

以 #define 開頭的前處理指令有四種功能: 宣告某一個代號的值。 產生符號常數 (symbolic constant)。 產生巨集 (macro)。 宣告某一個代號已經被設定。

除了包括在字串 (string) 之內的文字以外,所有吻合的文字,都將被代號直接取代。例如: 以 #define開頭的前處理指令 #define 代號 被取代文字 除了包括在字串 (string) 之內的文字以外,所有吻合的文字,都將被代號直接取代。例如: #define and && #define or || #define not !

範例程式LogicTest.cpp // 前處理指令 #define and && #define or || #define not ! #include <iostream> using namespace std;

cout << "((t1 > 0.8) and (t2 <0.9) or (t1>0.2))= " // ------ 主程式 --------------------------- int main() { float t1,t2; t1=0.5; t2=t1*0.2; cout << "((t1 > 0.8) and (t2 <0.9) or (t1>0.2))= " << ((t1 > 0.8) and (t2 <0.9) or (t1>0.2)) << endl; cout << " not(t1 > t2) = " << not(t1 > t2) << endl; return 0; }

程式執行結果 ((t1> 0.8) and (t2 <0.9) or (t1>0.2))= 1 not(t1 > t2) = 0

宣告符號常數(symbolic constant) 符號常數因為直接取代程式內的代號,本身並不佔用記憶空間,而每個常數在定義時即擁有自己的記憶空間。 #define RAND_MAX 0x7FFFU #define PI 3.1415926 比較好的做法是使用常數。例如: const double PI = 3.1415926; const double PI = 2.0*asin(1.0);

前處理指令內禁用的代號 代 號 意 義 --LINE-- 行號 --FILE-- 檔名 --DATE-- 編譯日期 --TIME-- 代 號 意 義 --LINE-- 行號 --FILE-- 檔名 --DATE-- 編譯日期 --TIME-- 編譯時間

行號不會加在程式裹面,程式的檔案名稱也沒有真的被更動,這個指令的最大用途在於大型檔案的除錯 (debugging)。 以 #line開頭的前處理指令 行號不會加在程式裹面,程式的檔案名稱也沒有真的被更動,這個指令的最大用途在於大型檔案的除錯 (debugging)。 #line 120 #line 120 "Test File.cpp"

範例程式Reserved.cpp 使用保留代號 #include <iostream> using namespace std; // ---- 主程式 ---------------------------- int main() { cout << "行號 : " << --LINE-- << endl; cout << "檔名 : " << --FILE-- << endl; cout << "編譯日期: " << --DATE-- << endl; cout << "編譯時間: " << --TIME-- << endl;

#line 120 "Test File.cpp" cout << "執行 #line 120 \"Test File.cpp\"之後: " << endl; cout << "行號 : " << --LINE-- << endl; cout << "檔名 : " << --FILE-- << endl; return 0; }

程式執行結果 行號 : 7 檔名 : Reserved.cpp 編譯日期 : Sep 13 2004 編譯時間 : 09:30:38 行號 : 7 檔名 : Reserved.cpp 編譯日期 : Sep 13 2004 編譯時間 : 09:30:38 執行 #line 120 "Test File.cpp"之後: 行號 : 122 檔名 : Test File.cpp

使用 #define 設定巨集(macro) 巨集指令的參數直接取代巨集本體部份的代號。例如: #define MAX(x,y) ((x) > (y) ? (x) : (y)) 它的功能相當於下列的inline樣版函數: template <class T> inline const T& MAX(const T& x, const T& y) {return x > y ? x : y;}

巨集本體部份的代號 在執行時會被引數直接取代 如果設定了一個叫做PRODUCT的巨集: #define PRODUCT(x,y) (x * y) 則 double F1 = 12.5, F2 = 8.38; cout << PRODUCT(F1+2, F2+6) << endl; 相當於執行: cout << 12.5 + 2 * 8.38 + 6 << endl;

PRODUCT巨集和inline樣版函數 #define PRODUCT(x,y) ((x) * (y)) 它的功能相當於下列的inline樣版函數: template <class T> inline const T& PRODUCT(const T& x, const T& y) {return x*y;}

將巨集指令的參數名稱直接以字串的型式輸出 只要將巨集本體部份相對於參數的代號前加上「#」即可。 例如: #define ShowValue(x) \ { \ cerr << #x << " 的值是: " << x << end \ } 如果我們在程式中執行下列敘述: double F1= 12.5; ShowValue(F1); 結果: F1的值是: 12.5

合併巨集指令的參數 例如,定義一個名叫 Merge的巨集: 如果在程式中執行下列敘述: 可以得到下列結果: #define Merge(x, y) x##y 如果在程式中執行下列敘述: double F1= 12.5; cout << "執行 Merge(F,1) 的結果是: " << Merge(F,1) << endl; 可以得到下列結果: 執行 Merge(F,1) 的結果是: 12.5

範例程式MacroTest.cpp: 建立和使用 MAX、PRODUCT、Merge,和ShowValue四個巨集指令 #include <iostream> using namespace std; // -- 巨集指令 --------------------------- #define MAX(x,y) ((x) > (y) ? (x) : (y)) #define PRODUCT(x,y) ((x) * (y)) #define Merge(x, y) x##y #define ShowValue(x) \ { \ cerr << #x << " 的值是: " << x << endl; \ cerr << "按 Enter 鍵繼續." << endl; \ cin.get(); \ }

// ---- 主程式 ------------------------------- int main() { int a = 3, b = 9; double F1= 12.5, F2=8.38; cout << "MAX(a, b) = " << MAX(a, b) << endl; cout << "MAX(F1, F2) = " << MAX(F1, F2) << endl; cout << "PRODUCT(F1, F2) = " << PRODUCT(F1+2, F2+6) << endl; ShowValue(F1); cout << "\n執行 Merge(F,2) 的結果是:" << Merge(F,2) << endl; return 0; }

程式執行結果 MAX(a, b) = 9 MAX(F1, F2) = 12.5 PRODUCT(F1, F2) = 208.51 按 Enter 鍵繼續. 執行 Merge(F,2) 的結果是: 8.38

條件式編譯(conditional compilation) 可以有選擇性地執行某些前處理指令,或有選擇性地只編譯原始程式碼的某些部份。常用的有下列數種: #ifdef #ifndef #else #endif #if defined() #if !defined() #elif

使用 #define設定代號 下列指令設定了代號Mark: #define Mark

以前處理指令避免重複加入同一個標頭檔 (1) 以前處理指令避免重複加入同一個標頭檔 (1) 例如:在標頭檔Commom.h內加入: #ifndef Common_h #define Common_h // 標頭檔 Common.h 的主要內容 // 如果 Common_h沒設定過才加入這個部份 #endif 在上式中,「#ifndef Common_h」也可以寫成 #if !defined(Common_h)

以前處理指令避免重複加入同一個標頭檔 (2) 以前處理指令避免重複加入同一個標頭檔 (2) 標頭檔Commom.h還可以寫成下列格式: #ifdef Common_h #else #define Common_h // … 標頭檔 Common.h 的主要內容 // … 如果 Common_h沒設定過才加入這個部份 #endif

範例程式Common.h 檔案MacroTest.cpp分成Common.h和Macro2.cpp 兩個檔案。 // Common.h #ifndef Common_h #define Common_h #include <iostream> using namespace std;

// -- 巨集指令 --------------------------- #define MAX(x,y) ((x) > (y) ? (x) : (y)) #define PRODUCT(x,y) ((x) * (y)) #define Merge(x, y) x##y #define ShowValue(x) \ { \ cerr << #x << " 的值是: " << x << endl; \ cerr << "按 Enter 鍵繼續." << endl; \ cin.get(); \ } #endif

範例程式Macro2.cpp // MacroTest.cpp // Macro2.cpp #include "Common.h" // ---- 主程式 -------------------- int main() { int a = 3, b = 9; double F1= 12.5, F2=8.38;

cout << "MAX(a, b) = " << MAX(a, b)<< endl; cout << "MAX(F1, F2) = " << MAX(F1, F2) << endl; cout << "PRODUCT(F1, F2) = " << PRODUCT(F1+2, F2+6) << endl; ShowValue(F1); cout << "\n執行 Merge(F,2) 的結果是: " << Merge(F,2) << endl; return 0; }

利用前處理指令插入除錯專用的敘述 藉由 #define 和 #undef前處理指令來做為執行的開關。例如,將巨集Breakpoint以下列的方式包裹起來: #define Debug #if defined(Debug) #define Breakpoint(x) { \ cerr << #x << " 的值是: " << x << endl; \ cerr << "按 Enter 鍵繼續." << endl; \ cin.get(); \ } #else #endif

藉由「#if 0」和「#endif」把要暫時忽略不編譯的區域包圍起來。如下列語法所示: 利用前處理指令暫時忽略部份程式 藉由「#if 0」和「#endif」把要暫時忽略不編譯的區域包圍起來。如下列語法所示: // ---- 其它敘述 ---- #if 0 // ---- 暫時不處理的區域 #endif

利用assert( ) 協助除錯 標頭檔 <cassert> 提供了函數 assert()。可以使用 #define NDEBUG #undef NDEBUG 做為函數assert()的開關。 assert(i<15); 一旦 I 大於或等於15,就會立即關閉程式,並發出錯誤訊息: Assertion failed: i < 15, file Test.cpp, line 40

範例程式Debug.cpp // Debug.cpp #define Debug #if defined(Debug) #define Breakpoint(x) \ { \ cerr << #x << “ 的值是: “ << x << endl; \ cerr << “按 Enter 鍵繼續.” << endl; \ cin.get(); \ } #else #define Breakpoint(x) #endif #undef NDEBUG

#include <iomanip> #include <iostream> #include <stdlib> #include <cassert> using namespace std; inline double Rand() // 定義 inline 函數 Rand() {return double(rand())/RAND_MAX;}

// ---- 主程式 ----------------------------- int main() { srand(int(time(0))); const int Size = 20; double Data[Size]; for (int i=0; i<Size; i++) Data[i]= 10.0*Rand()-5.0; assert(i<Size); } Breakpoint(Data[Size-1]); return 0;

程式執行結果 (因為程式會產生亂數,每一次執行結果都不相同。) Data[Size-1] 的值是: 1.72658 按Enter鍵繼續。

#pragma前處理指令 有某些特殊的前處理指令可以被某些編譯器接受,例如 #pragma warn -nak

#error 前處理指令 下列前處理指令: 這個語法相當於下列指令: #ifndef __cplusplus #error Must use C++ for the type bcd. #endif 這個語法相當於下列指令: cerr << “ Must use C++ for the type bcd.”;