#include<stdio.h>
#include<string.h>
int main()
{
FILE * handle;
char con[100];
//第一種使用fopen的方式,windows系統(tǒng)是直接輸入文件的絕對(duì)路徑需要這種方式"e:\\aaa.txt",注意是兩個(gè)反斜杠,一個(gè)反斜杠的話就錯(cuò)了
//handle=fopen("e:\aaa.txt","r");
//第二種使用fopen的方式,利用一個(gè)字符串來(lái)保存文件路徑和名字,運(yùn)行程序后,在dos下提示你輸入路徑名字,可以輸入"e:\\aaa.txt",
//或者"e:\aaa.txt",也就是說(shuō)dos下一個(gè)反斜杠或者兩個(gè)反斜杠都是正確的
//char buf[80];
//printf("please input the filename you want to open:");
//gets(buf);
//handle=fopen(buf,"r");
//利用一個(gè)初始化好的字符串也可以正確的使用fopen,以下這幾種初始化方式都是正確的都是兩個(gè)反斜杠
//char buf[]="e:\\aaa.txt";const char buf[100]="e:\\aaa.txt";
char *buf="e:\\aaa.txt";
handle=fopen(buf,"r");
if(!handle)
perror("can not open this file\n");
else
printf("you have opened this file successfully!\n");
fgets(con,100,handle);
printf("the content of file is:%s\n",con);
fclose(handle);
return 0;
}
主要介紹了fopen函數(shù)的第一個(gè)參數(shù)的使用,代碼里面說(shuō)的已經(jīng)很清楚了,其余類似fopen的函數(shù)的使用也一樣
摘要: linux文件權(quán)限的說(shuō)明,和chmod命令的使用
閱讀全文
關(guān)于PATH的作用:
PATH說(shuō)簡(jiǎn)單點(diǎn)就是一個(gè)字符串變量,當(dāng)輸入命令的時(shí)候LINUX會(huì)去查找PATH里面記錄的路徑。比如在根目錄/下可以輸入命令ls,在/usr目錄下也可以輸入ls,但其實(shí)ls這個(gè)命令根本不在這個(gè)兩個(gè)目錄下,事實(shí)上當(dāng)你輸入命令的時(shí)候LINUX會(huì)去/bin,/usr/bin,/sbin等目錄下面去找你此時(shí)輸入的命令,而PATH的值恰恰就是/bin:/sbin:/usr/bin:……。其中的冒號(hào)使目錄與目錄之間隔開(kāi)。
關(guān)于新增自定義路徑:
現(xiàn)在假設(shè)你新安裝了一個(gè)命令在/usr/locar/new/bin下面,而你又想像ls一樣在任何地方都使用這個(gè)命令,你就需要修改環(huán)境變量PATH了,準(zhǔn)確的說(shuō)就是給PATH增加一個(gè)值/usr/locar/new/bin。你只需要一行bash命令export PATH=$PATH:/usr/locar/new/bin。這條命令的意思太清楚不過(guò)了,使PATH自增:/usr/locar/new/bin,既PATH=PATH+":/usr/locar/new/bin";通常的做法是把這行bash命令寫到/root/.bashrc的末尾,然后當(dāng)你重新登陸LINUX的時(shí)候(應(yīng)該是linux啟動(dòng)時(shí)就會(huì)執(zhí)行這個(gè)文件),新的默認(rèn)路徑就添加進(jìn)去了。當(dāng)然這里你直接用source /root/.bashrc執(zhí)行這個(gè)文件重新登陸了。你可以用echo $PATH命令查看PATH的值。
關(guān)于刪除自定義路徑:
當(dāng)某天你發(fā)現(xiàn)你新增的路徑/usr/locar/new/bin已經(jīng)沒(méi)用了的話,你可以修改/root/.bashrc文件里面你新增的路徑?;蛘吣憧梢孕薷?etc/profile文件刪除你不需要的路徑.
一般來(lái)說(shuō),配置交叉編譯工具鏈的時(shí)候需要指定編譯工具的路徑,此時(shí)就需要設(shè)置環(huán)境變量。例如我的mips-linux-gcc編譯器在“/opt/au1200_rm/build_tools/bin”目錄下,build_tools就是我的編譯工具,則有如下三種方法來(lái)設(shè)置環(huán)境變量:
--------------------------------------------
臨時(shí)環(huán)境變量(重啟后消失)
-----------------------------------------------------
1、直接用export命令:
#export PATH=$PATH:/opt/au1200_rm/build_tools/bin
查看是否已經(jīng)設(shè)好,可用命令export查看:
[root@localhost bin]# export
declare -x BASH_ENV="/root/.bashrc"
declare -x G_BROKEN_FILENAMES="1"
declare -x HISTSIZE="1000"
declare -x HOME="/root"
declare -x HOSTNAME="localhost.localdomain"
declare -x INPUTRC="/etc/inputrc"
declare -x LANG="zh_CN.GB18030"
declare -x LANGUAGE="zh_CN.GB18030:zh_CN.GB2312:zh_CN"
declare -x LESSOPEN="|/usr/bin/lesspipe.sh %s"
declare -x LOGNAME="root"
declare -x LS_COLORS="no=00:fi=00:di=01;34:ln=01;36:pi=40;33:so=01;35:bd=40;33;01:cd=40;33;01:or=01;05;37;41:mi=01;05;37;41:ex=01;32:*.cmd=01;32:*.exe=01;32:*.com=01;32:*.btm=01;32:*.bat=01;32:*.sh=01;32:*.csh=01;32:*.tar=01;31:*.tgz=01;31:*.arj=01;31:*.taz=01;31:*.lzh=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.gz=01;31:*.bz2=01;31:*.bz=01;31:*.tz=01;31:*.rpm=01;31:*.cpio=01;31:*.jpg=01;35:*.gif=01;35:*.bmp=01;35:*.xbm=01;35:*.xpm=01;35:*.png=01;35:*.tif=01;35:"
declare -x MAIL="/var/spool/mail/root"
declare -x OLDPWD="/opt/au1200_rm/build_tools"
declare -x PATH="/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/X11R6/bin:/root/bin:/opt/au1200_rm/build_tools/bin"
declare -x PWD="/opt/au1200_rm/build_tools/bin"
declare -x SHELL="/bin/bash"
declare -x SHLVL="1"
declare -x SSH_ASKPASS="/usr/libexec/openssh/gnome-ssh-askpass"
declare -x SSH_AUTH_SOCK="/tmp/ssh-XX3LKWhz/agent.4242"
declare -x SSH_CLIENT="10.3.37.152 2236 22"
declare -x SSH_CONNECTION="10.3.37.152 2236 10.3.37.186 22"
declare -x SSH_TTY="/dev/pts/2"
declare -x TERM="linux"
declare -x USER="root"
declare -x USERNAME="root"
可以看到,環(huán)境變量已經(jīng)設(shè)好,PATH里面已經(jīng)有了我要加的編譯器的路徑。
里去操作了。
永久環(huán)境變量
--------------------------------------------------------
2、修改profile文件:
所有用戶(不安全)
修 改/etc/profile(對(duì)所有用戶都是有效的)
#vi /etc/profile
在里面加入:
export PATH="$PATH:/opt/au1200_rm/build_tools/bin"
3. 修改.bashrc文件:
# vi /~/.bashrc
(單獨(dú)用戶)
修改~/.bashrc文件。 htt(74)p://www.icwin.net/bbs http://www.wantso.com (每個(gè)用戶目錄下都有,ls -all)
cd ~
vi .bashrc
在里面加入:
export PATH="$PATH:/opt/au1200_rm/build_tools/bin"
后兩種方法一般需要重新注銷系統(tǒng)才能生效,最后可以通過(guò)echo命令測(cè)試一下:
# echo $PATH
看看輸出里面是不是已經(jīng)有了/my_new_path這個(gè)路徑了。
-----------------------------------------------------------------------------------------------------------------------
“/bin”、“/sbin”、“/usr/bin”、“/usr/sbin”、“/usr/local/bin”等路徑已經(jīng)在系統(tǒng)環(huán)境變量中了,如果可執(zhí)行文件在這幾個(gè)標(biāo)準(zhǔn)位置,在終端命令行輸入該軟件可執(zhí)行文件的文件名和參數(shù)(如果需要參數(shù)),回車即可。
如果不在標(biāo)準(zhǔn)位置,文件名前面需要加上完整的路徑。不過(guò)每次都這樣跑就太麻煩了,一個(gè)“一勞永逸”的辦法是把這個(gè)路徑加入環(huán)境變量。命令 “PATH=$PATH:路徑”可以把這個(gè)路徑加入環(huán)境變量,但是退出這個(gè)命令行就失效了。要想永久生效,需要把這行添加到環(huán)境變量文件里。有兩個(gè)文件可選:“/etc/profile”和用戶主目錄下的“.bash_profile”,“/etc/profile”對(duì)系統(tǒng)里所有用戶都有效,用戶主目錄下的“.bash_profile”只對(duì)這個(gè)用戶有效。
“PATH=$PATH:路徑1:路徑2:...:路徑n”,意思是可執(zhí)行文件的路徑包括原先設(shè)定的路徑,也包括從“路徑1”到“路徑n”的所有路徑。當(dāng)用戶輸入一個(gè)一串字符并按回車后,shell會(huì)依次在這些路徑里找對(duì)應(yīng)的可執(zhí)行文件并交給系統(tǒng)核心執(zhí)行。那個(gè)“$PATH”表示原先設(shè)定的路徑仍然有效,注意不要漏掉。某些軟件可能還有“PATH”以外類型的環(huán)境變量需要添加,但方法與此相同,并且也需要注意“$”。
注意,與DOS/Window不同,UNIX類系統(tǒng)環(huán)境變量中路徑名用冒號(hào)分隔,不是分號(hào)。另外,軟件越裝越多,環(huán)境變量越添越多,為了避免造成混亂,建議所有語(yǔ)句都添加在文件結(jié)尾,按軟件的安裝順序添加。
格式如下():
# 軟件名-版本號(hào)
PATH=$PATH:路徑1:路徑2:...:路徑n
其他環(huán)境變量=$其他環(huán)境變量:...
在“profile”和“.bash_profile”中,“#”是注釋符號(hào),寫在這里除了視覺(jué)分隔外沒(méi)有任何效果。
設(shè)置完畢,注銷并重新登錄,設(shè)置就生效了。如果不注銷,直接在shell里執(zhí)行這些語(yǔ)句,也能生效,但是作用范圍只限于執(zhí)行了這些語(yǔ)句的shell。
相關(guān)的環(huán)境變量生效后,就不必老跑到軟件的可執(zhí)行文件目錄
條件編譯,有三種格式
1 #if 表達(dá)式
程序段1
#else
程序段2
#endif
很簡(jiǎn)單,表達(dá)式為真編譯1,否則編譯2。
2 #ifdef 標(biāo)識(shí)符
程序段1
#else
程序段2
#endif
如果標(biāo)識(shí)符已用#define定義過(guò),則為真編譯1,否則編譯2
3 和2的基本一致就是把ifdef換成ifndef。用法是為假編譯1,否則2
比如#include <stdio.h>
int main()
{
#ifdef _DEBUG
printf("hello world\n");
#else
printf("no debug");
#endif
return 0;
}
在linux用gcc編譯是,如果使用gcc -D_DEBUG -o main main.c。則就是說(shuō)明定義過(guò)_DEBUG,運(yùn)行結(jié)果是hello world。注意是-D選項(xiàng),-D后面緊跟著標(biāo)識(shí)符名字
如果使用:gcc -o main mian.c,怎說(shuō)明沒(méi)有定義標(biāo)識(shí)符,運(yùn)行結(jié)果是no debug了。
當(dāng)然,也可以直接再代碼里顯示寫上一句:#define _DEBUG,也能有相同效果。
宏的使用的核心,就是替換,換是最關(guān)鍵的。
1、不帶參數(shù)的宏定義
這是最簡(jiǎn)單的了,比如#define PI 3.1415926
預(yù)編譯的時(shí)候,把代碼中的PI替換就行了。一般情況下宏名用大寫字母,不要在行末加分號(hào)。
2、帶參數(shù)的宏定義
不只是進(jìn)行宏體的替換,還要進(jìn)行參數(shù)的替換。
比如:#define MAX(x,y) (x>y)?x:y
宏展開(kāi)的時(shí)候要將語(yǔ)句中宏名后面的括號(hào)內(nèi)的實(shí)參代替形參。另外為了避免發(fā)生錯(cuò)誤,凡是帶運(yùn)算符的參數(shù)要用圓括號(hào)括起來(lái)。
3、不常見(jiàn)但是很重要的用法
(1)#define FUN(a) "a"
那么當(dāng)輸入FUN(345)是,照樣會(huì)被替換成“a”,無(wú)論宏的實(shí)參是什么,都不會(huì)影響其被替換成"a"的命運(yùn)。
也就是說(shuō),""內(nèi)的字符不被當(dāng)成形參,即使它和一模一樣。
(2)有參宏定義中#的用法
#define STR(str) #str
str前面的那個(gè)#用于把宏定義中的參數(shù)兩端加上字符串的""
比如代碼中有STR(my#name),那么在展開(kāi)的時(shí)候被替換成"my#name"。
一般由任意字符都可以做形參,但以下情況會(huì)出錯(cuò):
STR())這樣,編譯器不會(huì)把“)”當(dāng)成STR()的參數(shù)。
STR(,)同上,編譯器不會(huì)把“,”當(dāng)成STR的參數(shù)。
STR(A,B)如果實(shí)參過(guò)多,則編譯器會(huì)把多余的參數(shù)舍去。(VC++2008為例)
STR((A,B))會(huì)被解讀為實(shí)參為:(A,B),而不是被解讀為兩個(gè)實(shí)參,第一個(gè)是(A第二個(gè)是B)。
(3) 有參宏定義中##的用法
#define WIDE(str) L##str
則會(huì)將形參str的前面加上L
比如:WIDE("abc")就會(huì)被替換成L"abc"
如果有#define FUN(a,b) vo##a##b()
那么FUN(id ma,in)會(huì)被替換成void main()
再比如:
#define s5(a) supper_ ## a
#include <stdio.h>
void supper_printf(const char* p )
{
printf("this is supper printf:\n%s\n",a);
}
int main()
{
s5(printf)("hello owrld");//就是調(diào)用函數(shù)supper_printf.
return 0;
}
(4) 多行宏定義:
#define doit(m,n) for(int i=0;i<(n);++i)\
{\
m+=i;\
}
關(guān)鍵是要在每一個(gè)換行的時(shí)候加上一個(gè) "\ " ,最后一行不用加。這樣使用的時(shí)候就可以用doit(m,n)來(lái)代替for循環(huán)結(jié)構(gòu)了。
還是先看看csapp上的解釋:并發(fā)(concurrency)是指一個(gè)通用上的概念,指一個(gè)同時(shí)具有多個(gè)活動(dòng)的系統(tǒng);并行(parallelism)指的是用并發(fā)使一個(gè)系統(tǒng)運(yùn)行得更快。
百度的解釋:并發(fā), 在
操作系統(tǒng)中,是指一個(gè)時(shí)間段中有幾個(gè)程序都處于已啟動(dòng)運(yùn)行到運(yùn)行完畢之間,且這幾個(gè)程序都是在同一個(gè)
處理機(jī)上運(yùn)行,但任一個(gè)時(shí)刻點(diǎn)上只有一個(gè)程序在處理機(jī)上運(yùn)行。也就是實(shí)際上,并發(fā)使指的在邏輯上,宏觀上,一個(gè)計(jì)算機(jī)能夠同時(shí)執(zhí)行多個(gè)任務(wù)多個(gè)程序,但是微觀上看,在同一個(gè)時(shí)刻,只有一個(gè)程序在運(yùn)行,但是由于處理器速度非??斓脑趲讉€(gè)程序來(lái)回切換,讓我們覺(jué)得是好幾個(gè)程序同時(shí)在執(zhí)行。
而并行則是真正的讓計(jì)算機(jī)在物理上同時(shí)執(zhí)行多個(gè)活動(dòng)。
舉個(gè)例子,媽媽(cpu)在上午10點(diǎn)后開(kāi)始做家務(wù)(程序),首先是收拾房間,收拾完房間后,開(kāi)始洗衣服,洗完衣服后開(kāi)始做午飯,那么到中午12點(diǎn),媽媽一共做了3件事情(程序),從宏觀上看,媽媽在一個(gè)上午的時(shí)間同時(shí)做了3個(gè)家務(wù),但是實(shí)際上這三件事并不是同時(shí)做的。而如果媽媽這么選擇做家務(wù):在收拾房間的同時(shí),把衣服扔到洗衣機(jī)里讓洗衣機(jī)洗著,同時(shí)又讓電飯鍋蒸著米飯,等媽媽收拾完房間的同時(shí)衣服也洗好了,飯也做熟了。三件事情等于是真正上的同時(shí)執(zhí)行的,這就是并行。很明顯我們會(huì)發(fā)現(xiàn),并行的速度要遠(yuǎn)遠(yuǎn)快于并發(fā)。
當(dāng)然并發(fā)和并行的具體實(shí)現(xiàn)遠(yuǎn)遠(yuǎn)很復(fù)雜,這只是先從概念上區(qū)分開(kāi)并發(fā)和并行。
先寫出將要解釋的哪幾對(duì)概念:
程序、進(jìn)程和線程
并發(fā)和并行
多線程和超線程
單核和多核。(
必須先咒罵一句,以下內(nèi)容其實(shí)是第二遍寫了,在第一次發(fā)表的時(shí)候,沒(méi)有發(fā)表成功,結(jié)果全都沒(méi)有了,還得重新寫一遍,第一次寫的內(nèi)容其實(shí)很多,第二次是在沒(méi)有心思寫太多了,只寫主要的了,TMD....)
程序是死的,只是安裝到你的電腦上的一堆文件而已,你不允許它,它就靜靜躺在那里,什么都不做。進(jìn)程:很專業(yè)的解釋是,操作系統(tǒng)對(duì)一個(gè)運(yùn)行的程序的一種抽象(CSAPP)。果然是很抽象的,抽象的基本不懂。進(jìn)程就是代表程序在電腦里運(yùn)行的,每一個(gè)程序至少有一個(gè)進(jìn)程,進(jìn)程是進(jìn)程是一個(gè)具有一定獨(dú)立功能的程序關(guān)于某個(gè)數(shù)據(jù)集合的一次運(yùn)行活動(dòng)。當(dāng)賦予死的程序以生命時(shí),它就成了一個(gè)活動(dòng)的實(shí)體,稱之為進(jìn)程。每一個(gè)進(jìn)程運(yùn)行后,都會(huì)向cpu索要相應(yīng)的系統(tǒng)資源,都會(huì)有自己一定的地址空間,在這空間里會(huì)存放文本區(qū)域(text region)、數(shù)據(jù)區(qū)域(data region)和
堆棧(stack region)。文本區(qū)域存儲(chǔ)處理器執(zhí)行的代碼;數(shù)據(jù)區(qū)域存儲(chǔ)變量和進(jìn)程執(zhí)行期間使用的動(dòng)態(tài)分配的內(nèi)存;堆棧區(qū)域存儲(chǔ)著活動(dòng)過(guò)程調(diào)用的指令和本地變量。線程,線程,有時(shí)被稱為
輕量級(jí)進(jìn)程(Lightweight Process,LWP),是程序執(zhí)行流的最小
單元。每一個(gè)進(jìn)程都至少有一個(gè)主線程,進(jìn)程向系統(tǒng)申請(qǐng)一段地址空間,而線程并不擁有專屬于自己的地址空間,每個(gè)線程都只擁有一點(diǎn)點(diǎn)必不可少的資源,進(jìn)程中所有的線程共享進(jìn)程的資源。線程一個(gè)創(chuàng)建和撤銷另外一個(gè)線程。線程其實(shí)才是真正利用cpu的單位,它是能獨(dú)立運(yùn)行的基本單位,也是獨(dú)立調(diào)度和分派的單位??梢赃@么認(rèn)為,進(jìn)程向cpu申請(qǐng)了地址空間后,然后把真正要做的工作全部交給了線程去做,但是線程使用的資源是由進(jìn)程代表申請(qǐng)的。
拿一個(gè)c程序舉例子來(lái)說(shuō)明下進(jìn)程和線程的關(guān)系,一個(gè)c程序只有一個(gè)主函數(shù),main函數(shù),但是可以擁有其他很多子函數(shù),main函數(shù)是c程序運(yùn)行的切入點(diǎn),通過(guò)main函數(shù)可以調(diào)用其他子函數(shù),main函數(shù)和其他子函數(shù)共享全局變量,也可以相互之間很方便的傳遞數(shù)據(jù)。這里,可以把進(jìn)程看成一個(gè)c程序,一個(gè)進(jìn)程也只擁有一個(gè)主線程,主線程就是相當(dāng)于main函數(shù),線程之間共享數(shù)據(jù),也可以相互很方便的傳遞數(shù)據(jù)。
再舉一個(gè)更生動(dòng)的數(shù)據(jù)。說(shuō):
一堆肉,是死的,什么都做不了,但是一堆肉組成了一個(gè)人,人是活的有生命的,人又由很多器官組成,當(dāng)人想要做什么事情的時(shí)候,其實(shí)是由大腦這個(gè)器官調(diào)配其余器官來(lái)真正做的??梢哉f(shuō)人在這個(gè)社會(huì)上占有一定的資源,但是真正使用這些資源的是器官,但是我們不能說(shuō)器官占有這些資源。這里,程序就是一堆肉,進(jìn)程就是一個(gè)人,線程就是器官,其中主線程是大腦。
這些概念都有所了解,但是要想完全說(shuō)清楚很難了,等我逐一弄懂,并且確定自己的了解是正確的后,我會(huì)貼出來(lái)的。
WAITING...
首先看名字不要太多誤會(huì),我說(shuō)的意思是不要看《深入理解計(jì)算機(jī)系統(tǒng)》(裘奕利雷迎春翻譯),但是《computer system a programmer‘s perspective》這本書(shū)是一定要看的。
有人說(shuō)這兩本書(shū)不是一樣嘛,一個(gè)英文原版一個(gè)中文翻譯版。
非也!
當(dāng)初自恃英文水平不是很高,不敢看英文原版的,于是乎買了本中文版??催@本書(shū)也有段時(shí)間了,現(xiàn)在是越看越窩火,翻譯的真的真的是太差勁了。
先從翻譯的這個(gè)中文破名字說(shuō)起,英文名字直接翻譯漢語(yǔ)大概應(yīng)該是:以一個(gè)程序員的角度來(lái)看計(jì)算機(jī)系統(tǒng)。不知道怎么就給翻譯成了深入理解計(jì)算機(jī)系統(tǒng)。我想百分之90的人們看到這個(gè)名字,都不會(huì)聯(lián)系到實(shí)際的書(shū)的內(nèi)容。
翻開(kāi)書(shū)正文內(nèi)容第一頁(yè)——出版者的話,第六個(gè)字就很明顯的錯(cuò)了,也不知道是翻譯的錯(cuò)誤或者說(shuō)是作者語(yǔ)文水平太差或者說(shuō)是印刷錯(cuò)誤(這個(gè)錯(cuò)誤還勉強(qiáng)可以接受吧),由此管中窺豹,可見(jiàn)翻譯者或者出版社的態(tài)度了,至少不是十分認(rèn)真了,書(shū)的僅僅第六個(gè)字就弄錯(cuò)了。
再談,書(shū)的內(nèi)容的翻譯,我想如果要是季羨林大師再世的話,僅從漢語(yǔ)的角度看看這本中文書(shū)(雖然我可以基本肯定大師不太懂計(jì)算機(jī)系統(tǒng)和c吧),非得氣死。從我一個(gè)工科學(xué)生對(duì)語(yǔ)文的了解,就可以發(fā)現(xiàn)通篇的漢語(yǔ)語(yǔ)法錯(cuò)誤,不是缺主謂賓就是缺定狀補(bǔ),有的錯(cuò)誤憑著多年對(duì)漢語(yǔ)的應(yīng)用可以自己理解過(guò)來(lái),但是通篇很多的錯(cuò)誤實(shí)在讓人受不了,還有更過(guò)分的是對(duì)一些專業(yè)術(shù)語(yǔ)的翻譯,從漢語(yǔ)表面的意思實(shí)在聯(lián)想不到和這個(gè)術(shù)語(yǔ)的實(shí)際意義有啥相關(guān)系。再有就是很多很多的超長(zhǎng)句子,一個(gè)句子有太多的修辭詞定語(yǔ)狀語(yǔ),我說(shuō)你丫的翻譯者就不能把長(zhǎng)句分成幾個(gè)短句??!
本來(lái)有些內(nèi)容就不是很好理解,很晦澀,再加上這個(gè)糟糕的翻譯,在想深入理解書(shū)中的內(nèi)容時(shí),真是太痛苦了!我真有一種想痛罵的沖動(dòng)??!
以后再買一些英文技術(shù)書(shū)籍時(shí),堅(jiān)決只買英文版的,雖然開(kāi)始看時(shí)會(huì)慢些,需要對(duì)著個(gè)英文翻譯軟件查不認(rèn)識(shí)的單詞,但后期肯定會(huì)越來(lái)越好的。
強(qiáng)烈建議大家學(xué)這書(shū)的內(nèi)容時(shí),買英文版的,至少不要買這一版的中文版!!
另外再點(diǎn)名另外一本中文翻譯的書(shū)《數(shù)據(jù)結(jié)構(gòu)和算法分析:C++描述》,翻譯的更差勁!
點(diǎn)名表?yè)P(yáng)一本書(shū)《C++ primer》,這本書(shū)的中文翻譯我自認(rèn)為在我看到的眾多翻譯過(guò)來(lái)的書(shū)中是最好的了!
第一遍看這本書(shū)的時(shí)候,稍微掃了一遍這個(gè)內(nèi)容,當(dāng)時(shí)看起來(lái)有時(shí)生硬,不是很懂,等于跳了過(guò)去了?,F(xiàn)在再看,感覺(jué)很有用,也基本能看明白了。說(shuō)個(gè)題外話,有時(shí)候看有些內(nèi)容,第一次看到的時(shí)候,覺(jué)得很難理解很難理解,就是反復(fù)看好幾遍也理解不了。那么不妨就放下這段內(nèi)容,也許你學(xué)過(guò)后面的內(nèi)容的后,有天你再返回來(lái)看當(dāng)初不懂的,就豁然開(kāi)朗了,學(xué)習(xí)這本c++primer的過(guò)程中,真的有太多的這種體會(huì)了。
開(kāi)始正題:
#define 指示的接受后面的名字,并把這個(gè)名字定義為預(yù)處理器變量,常用大寫。
#ifndef 字面意思就是if not define 如果沒(méi)有定義。就是如果后面的名字沒(méi)有被定義成預(yù)處理器變量,那么這句話后所有的程序都將被執(zhí)行,直到遇見(jiàn)#endif
說(shuō)明具體用法和意義。
假如我自己寫了兩個(gè)頭文件one.h,和two.h。其中one.h包括的是一個(gè)類的定義;two.h由于也要用到這個(gè)類,所以這個(gè)頭文件里面必然要有一行程序:#include“one.h”。
而我們的主程序里面,開(kāi)始必然要把我們自己定義的頭文件給加進(jìn)去,必然應(yīng)該有兩行程序:#include“one.h”和#include“two.h”,這樣實(shí)際上one.h這個(gè)頭文件被包含了兩次,那個(gè)類的也相當(dāng)于定義了兩次,必然編譯時(shí)會(huì)出現(xiàn)錯(cuò)誤,為了解決這個(gè)問(wèn)題。在one.h里應(yīng)該加入這么一段程序:
#ifndef ONE
#define ONE
//這里應(yīng)是one.h里面本來(lái)應(yīng)該有的代碼程序
#endif
這樣這個(gè)頭文件在主程序處理時(shí)只會(huì)被處理一次。因?yàn)椋寒?dāng)主程序首先碰到這句::#include“one.h,時(shí),由于是第一次處理one頭文件,ONE這個(gè)預(yù)處理器變量還沒(méi)有定義呢,所以會(huì)執(zhí)行#define ONE這個(gè)語(yǔ)句,ONE變量被定義了,頭文件one中的代碼也會(huì)被執(zhí)行了。當(dāng)主程序碰到這句:#include“two.h”,由于two頭文件中,也有這么一句:#include“one.h”,然后程序就會(huì)再次進(jìn)入到one這個(gè)頭文件中執(zhí)行,這是由于ONE這個(gè)變量在第一次執(zhí)行one這個(gè)頭文件時(shí)已經(jīng)被定義了,所以#ifndef ONE判斷失敗,不會(huì)執(zhí)行后續(xù)的代碼了,也就不會(huì)在執(zhí)行one頭文件中實(shí)際有用的代碼了。這樣保證了頭文件只會(huì)被處理一次。
因此應(yīng)該在自己編寫的每個(gè)頭文件中都加上保護(hù)符,避免頭文件被多次包含。