命令
引言
做c/c++編程的對#include指令都不會陌生,絕大多數人也都知道如何使用,但我相信仍有人對此是一知半解的,
C:
#include
C++:
#include
表示包含C/C++标準輸入輸出頭文件。包含指令不僅僅限于.h頭文件,可以包含任何編譯器能識别的C/C++代碼文件,包括.c、.hpp、.cpp、.hxx、.cxx等,甚至.txt、.abc等等都可以。
預處理器發現 #include 指令後,就會尋找指令後面<>中的文件名,并把這個文件的内容包含到當前文件中。被包含文件中的文本将替換源代碼文件中的#include 指令, 就像你把被包含文件中的全部内容鍵入到源文件中的這個位置一樣。
名詞解釋
preprocess
預處理:為方便編譯器處理而設置的一種機制,包括一些常用預處理指令和語句,我們統稱為預處理系統。
如#include #define #if...#else...#endif #pragma等
這些指令的實現是由編譯器來決定的(implementation specified)
提到預處理指令,順便說一下頭文件防止重複包含的2種方法
a.保護宏(暫且稱為Macro guard 宏衛兵?):
#ifndef _ABCDE_H
#define _ABCDE_H
/*
代碼部分
*/
#endif
在被包含過一次之後,宏_ABCDE_H已經有了,下次再碰到就會略過從#define _ABCDE_H開始到#endif之間的代碼
還有一種特定編譯器支持的指令:
b.#pragma once
能保證該文件(物理上的)隻被編譯一次,也能起到防止重複包含的作用
但這2種方式是有區别的:
a.Macro guard可移植性好,絕大多數編譯器都支持,而且萬一不小心拷貝了幾分相同的代碼也不會出問題,但你得确保這個宏名不會與其他的宏沖突,否則等編譯器報出一大堆錯誤的時候你可能會覺得莫名其妙;
b.#pragma once指令簡單,它能保證該文件(物理上的)隻被編譯一次,不用去費勁的想不同的宏名,但如果有幾份該文件的拷貝,顯然起不到作用。
declaration
聲明:指将一個名稱引入當前編譯單元,或者重新聲明一個前面已經聲明過的名稱,聲明指定了如何解釋一個名稱和該名稱具有的屬性;
例如:
int main(void)
{
int a; // 聲明了變量a,類型為int
int *pa; // 聲明了變量pa,類型為指向int型的指針類型
}
definition
定義:除了以下情況,聲明就是定義
a.聲明函數但不包括函數體;
b.聲明包含extern鍊接限定符,例如:extern int a;
c.聲明既沒有初始化語法,也沒有函數體;
d.類聲明中聲明靜态數據成員;
e.類名字聲明;
f.typedef聲明;
g.using聲明或者using指令;
以上情況适用于C具有的特征,C++則完全适用,一般來說定義要為其對象分配或預留存儲空間,而聲明則不用。
translation unit
編譯單元:一個源文件,.c .cpp等和它所包含的文件一起,在經過預處理之後形成一個源碼文件,标準稱之為translation unit(編譯單元)包括一系列的聲明和定義;一個program(程序)由一個或多個編譯單元組成。編譯器将各個編譯單元編譯為目标代碼(.obj),通過連接器(linker)将這些編譯後的編譯單元(即目标代碼)連接成完整的指令序列(可執行文件、靜态庫、動态庫等)。
one definition rule
一次定義規則:是指定義在所有進入連接的編譯單元中隻能有一次。
觀點、例子
A:頭文件隻放聲明
example_a.h
void function();
example_a.cpp:
#include "example_a.h"
void function()
{}
B.被包含的文件可以使用任意擴展名:
隻要是用符合标準的代碼編寫的文本文件,就可以使用#include來進行包含,包括.cpp .c等常見的源文件擴展名;
example_b_1.b
void function();
example_b_1.cpp:
#include "example_b_1.b"
void function()
{}
example_b_2.b
void function1();
void function2();
example_b_21.cpp:
void function1()
{}
example_b_22.cpp:
#include "example_b_1.b"
#include "example_b_21.cpp"
void function2()
{}
上面的例子中,example_b_21.cpp僅被包含在example_b_22.cpp中,不再被其他的文件包含,而且不加入工程中;
C.标準頭文件的使用
最新的C++标準庫中的一切内容都被放在名字空間std中(名字空間中的内容對外是不可見的),但是帶來了一個新問題,無數現有的C++代碼都依賴于使用了多年的僞标準庫中的功能,如聲明在;等頭文件中的功能,使用std包裝标準庫導緻現有代碼的不可用,為了兼容這種情況,标準委員會為包裝了std的那部分标準庫創建了新的頭文件,新的頭文件的文件名與舊的一樣,隻是沒有.h這個後綴,如;就變成了;。對于C頭文件,采用同樣的方法,但還在每個頭文件名前加了字符c,如;就變成了;,;變成了;。最好使用新的文件頭,使用新的文件頭的C++程序,需要使用using namespace std或者using namespace std::指定的類名,等方法來使需要的類對于我們的代碼可視。
用法
#include後面有兩種方式,<>;和""前者先在标準庫中查找,查找不到在path中查找。後者為文件路徑,若直接是文件名則在項目根目錄下查找
總結
既然是經常使用的東西,我們就應該明白它的原理,減少編程時的困惑,提高編程的效率。
舉例說明
例子
include.jsp:
An Include Test
The current date and time are
<%@ include file="date.jsp" %>
date.jsp:
<%@ page import="java.util.*" %>
<%= (new java.util.Date() ).toLocaleString() %>
Displays in the page:
The current date and time are
Aug 30, 1999 2:38:40
描述
<%@include %>指命将會在JSP編譯時插入一個包含文本或代碼的文件,當你使用<%@ include %>指命時,這個包含的過程就當是靜态的。靜态的包含就是指這個被包含的文件将會被插入到JSP文件中去,這個包含的文件可以是JSP文件,HTML文件,文本文件。如果包含的是JSP文件,這個包含的JSP的文件中代碼将會被執行。
如果你僅僅隻是用include 來包含一個靜态文件。那麼這個包含的文件所執行的結果将會插入到JSP文件中放<% @ include %>的地方。一旦包含文件被執行,那麼主JSP文件的過程将會被恢複,繼續執行下一行.
這個被包含文件可以是html文件,jsp文件,文本文件,或者隻是一段Java代碼,但是你得注意在這個包含文件中不能使用,,,标記,因為這将會影響在原JSP文件中同樣的标記 ,這樣做有時會導緻錯誤.
有一些<%@ include %>指命的行為是以特殊的JSP編譯條件為基礎,比如:
這個被包含的文件必須對所有客戶都有開放且必須f有效,或者它有安全限制
如果這個包含文件被改變,包含此文件的JSP文件将被重新編譯
屬性:
file="relativeURL"
這個包含文件的路徑名一般來說是指相對路徑,不需要什麼端口,協議,和域名,如下:
"error.jsp""/templates/onlinestore.html""/beans/calendar.jsp"
如果這個路徑以"/"開頭,那麼這個路徑主要是參照JSP應用的上下關系路徑,如果路徑是以文件名或目錄名開頭,那麼這個路徑就是正在使用的JSP文件的當前路徑.
在的JSP 1.2,有page、include與taglib三種Directive Elements(指令元素 -- 使用<%@ 與 %>包括).現在主要介紹page的用法.
page元素常用屬性:
info屬性:用于設定目前JSP頁面的基本信息,這個信息最後會轉換為Servlet程序中使用getServletInf()所取得的信息.
contentType屬性:用于設定MIME型态及網頁編碼方式,這個部份的設定是給浏覽器判斷該以什麼樣的方式顯示網頁文件,在Servlet中,這個部份是對應于HttpServletResponse對象的setContentType()方法.
import屬性:則相當于Java語法中的import.
page元素還包括其他屬性:
autoFlush:用于設定至客戶端的輸出串流是否要自動出清,預設是true,如果設定為false,而緩沖區滿了,将會産生例外。
buffer屬性:用于設定至客戶端的輸出串流緩沖區大小,預設是8KB。
errorPage:用于設定當JSP執行錯誤而産生例外時,該由哪一個頁面處理這個例外。
extends屬性:可以用來指定JSP網頁轉譯為Servlet程序之後,該繼承哪一個類别.
isErrorPage:用以設定JSP頁面是否為處理例外的頁面,這個屬性要與errorPage配合使用.
session屬性:可設定是否使用session對象,預設是true。
pageEncoding屬性:用于指定JSP網頁轉為Servlet編譯時采取的編碼方式,如此在編譯時才能正确的轉換程序代碼中設定的字符,預設是操作系統的語系設定。
isELIgnored:用以設定JSP網頁中是否忽略Expression Language,預設是false,如果設定為true,則Expression Language被會被轉譯,Expression Language在JSP 2.0成為标準規格之一。
例子:
<%@page info="JSP指令元素示範"%>
<%@page contentType="text/html;charset=Big5"%>
<%@page import="javax.servlet.jsp.HttpJspPage,java.util.Date"%>
<%= ((HttpJspPage)page).getServletInfo() %>
現在時間: <%= (new Date()).toString() %>
php中
include()語句包含并運行指定文件。
以下文檔也适用于require()。這兩種結構除了在如何處理失敗之外完全一樣。include(産生一個警告而require()則導緻一個緻命錯誤。換句話說,如果想在遇到丢失文件時停止處理頁面就用require()。include()就不是這樣,腳本會繼續運行。同時也要确認設置了合适的include_path。注意在php4.3.5之前,包含文件中的語法錯誤不會導緻程序停止,但從此版本之後會。
尋找包含文件的順序先是在當前工作目錄的相對的include_path下尋找,然後是當前運行腳本所在目錄相對的include_path下尋找。例如include_path是.,當前工作目錄是/www/,腳本中要include一個include/a.php并且在該文件中有一句include"b.php",則尋找b.php的順序先是/www/,然後是/www/include/。如果文件名以../開始,則隻在當前工作目錄相對的include_path下尋找。
當一個文件被包含時,其中所包含的代碼繼承了include所在行的變量範圍。從該處開始,調用文件在該行處可用的任何變量在被調用的文件中也都可用。不過所有在包含文件中定義的函數和類都具有全局作用域。
例子16-5.基本的include()例子
vars.php
$color='green';
$fruit='apple';
?>
test.php
echo"A$color$fruit";//A
include'vars.php';
echo"A$color$fruit";//Agreenapple
?>如果include出現于調用文件中的一個函數裡,則被調用的文件中所包含的所有代碼将表現得如同它們是在該函數内部定義的一樣。所以它将遵循該函數的變量範圍。
例子16-6.函數中的包含
functionfoo()
{
global$color;
include'vars.php';
echo"A$color$fruit";
}
/*vars.phpisinthescopeoffoo()so*
*$fruitisNOTavailableoutsideofthis*
*scope.$colorisbecausewedeclaredit*
*asglobal.*/
foo();//Agreenapple
echo"A$color$fruit";//Agreen
?>例子16-7.通過HTTP進行的include()
/*Thisexampleassumesthatwww.example.comisconfiguredtoparse.php*
*filesandnot.txtfiles.Also,'Works'heremeansthatthevariables*
*$fooand$barareavailablewithintheincludedfile.*/
//Won'twork;file.txtwasn'thandledbywww.example.comasphp
include'http://www.example.com/file.txt?foo=1&bar=2';
//Won'twork;looksforafilenamed'file.php?foo=1&bar=2'onthe
//localfilesystem.
include'file.php?foo=1&bar=2';
//Works.
include'http://www.example.com/file.php?foo=1&bar=2';
$foo=1;
$bar=2;
include'file.txt';//Works.
include'file.php';//Works.
?>相關信息參見使用遠程文件,fopen()和file()。
因為include()和require()是特殊的語言結構,在條件語句中使用必須将其放在語句組中(花括号中)。
例子16-8.include()與條件語句組
//ThisisWRONGandwillnotworkasdesired.
if($condition)
include$file;
else
include$other;
//ThisisCORRECT.
if($condition){
include$file;
}else{
include$other;
}
?>處理返回值:可以在被包括的文件中使用return()語句來終止該文件中程序的執行并返回調用它的腳本。同樣也可以從被包含的文件中返回值。可以像普通函數一樣獲得include調用的返回值。不過這在包含遠程文件時卻不行,除非遠程文件的輸出具有合法的php開始和結束标記(如同任何本地文件一樣)。可以在标記内定義所需的變量,該變量在文件被包含的位置之後就可用了。
因為include()是一個特殊的語言結構,其參數不需要括号。在比較其返回值時要注意。
例子16-9.比較include的返回值
//won'twork,evaluatedasinclude(('vars.php')=='OK'),i.e.include('')
if(include('vars.php')=='OK'){
echo'OK';
}
//works
if((include'vars.php')=='OK'){
echo'OK';
}
?>注:在php3中,除非是在函數中調用否則被包含的文件中不能出現return。在此情況下return()作用于該函數而不是整個文件。
例子16-10.include()和return()語句
return.php
$var='php';
return$var;
?>
noreturn.php
$var='php';
?>
testreturns.php
$foo=include'return.php';
echo$foo;//prints'php'
$bar=include'noreturn.php';
echo$bar;//prints1
?>$bar的值為1是因為include成功運行了。注意以上例子中的區别。第一個在被包含的文件中用了return()而另一個沒有。如果文件不能被包含,則返回FALSE并發出一個E_WARNING警告。
如果在包含文件中定義有函數,這些函數可以獨立于是否在return()之前還是之後在主文件中使用。如果文件被包含兩次,php5發出緻命錯誤因為函數已經被定義,但是php在return()之後不會抱怨函數已定義。推薦使用include_once()而不是檢查文件是否已包含并在包含文件中有條件返回。
另一個将php文件“包含”到一個變量中的方法是用輸出控制函數結合include()來捕獲其輸出,例如:
例子16-11.使用輸出緩沖來将php文件包含入一個字符串
$string=get_include_contents('somefile.php');
functionget_include_contents($filename){
if(is_file($filename)){
ob_start();
include$filename;
$contents=ob_get_contents();
ob_end_clean();
return$contents;
}
returnfalse;
}
?>要在腳本中自動包含文件,參見php.ini中的auto_prepend_file和auto_append_file配置選項。
注:由于這是一個語言結構而非函數,因此它無法被變量函數調用。
參見require(),require_once(),include_once(),readfile(),virtual()和include_path。
相關拓展
C語言中#include指令的作用域華中理工大學畢世紅當源程序很長時,可将其分成幾個文本文件。有兩種分法:一是工程制作(project-make);二是文件包含(#include)。兩者所不同的是,前者可以分别編譯,但當源文件較多時。在工程菜單中定義... n



















