⑴ 編譯原理:優先函數 f和g 到底怎麼看啊,不懂怎麼構造的 求解...
求算符優先函數的方法—迭代法
若已知運算符之間的優先關系,可按如下步驟構造優先函數:
1、對每個運算符a(包括#在內)令f(a)=g(a)=1
2、如果a⋗b且f(a)<=g(b),令f(a)=g(b)+1
3、如果a⋖b且f(a)>=g(b),令g(b)= f(a)+1
4、如果a≐b而f(a) ≠g(b),令min{f(a),g(b)}=max{f(a),g(b)}
5、重復2~4,直到過程收斂。如果重復過程中有一個值大於2n,則表明不存在算符優先函數。
⑵ C語言編譯原理是什麼
編譯共分為四個階段:預處理階段、編譯階段、匯編階段、鏈接階段。
1、預處理階段:
主要工作是將頭文件插入到所寫的代碼中,生成擴展名為「.i」的文件替換原來的擴展名為「.c」的文件,但是原來的文件仍然保留,只是執行過程中的實際文件發生了改變。(這里所說的替換並不是指原來的文件被刪除)
2、匯編階段:
插入匯編語言程序,將代碼翻譯成匯編語言。編譯器首先要檢查代碼的規范性、是否有語法錯誤等,以確定代碼的實際要做的工作,在檢查無誤後,編譯器把代碼翻譯成匯編語言,同時將擴展名為「.i」的文件翻譯成擴展名為「.s」的文件。
3、編譯階段:
將匯編語言翻譯成機器語言指令,並將指令打包封存成可重定位目標程序的格式,將擴展名為「.s」的文件翻譯成擴展名為「.o」的二進制文件。
4、鏈接階段:
在示例代碼中,改代碼文件調用了標准庫中printf函數。而printf函數的實際存儲位置是一個單獨編譯的目標文件(編譯的結果也是擴展名為「.o」的文件),所以此時主函數調用的時候,需要將該文件(即printf函數所在的編譯文件)與hello world文件整合到一起,此時鏈接器就可以大顯神通了,將兩個文件合並後生成一個可執行目標文件。
⑶ c與c++語言編譯器是如何識別關鍵字
根據編譯器的不同,有不同的識別方式,例如VC6.0使用系統內建關鍵字列表,如果用戶定義變數的時候使用了系統默認的關鍵字,則會在編譯的時候產生錯誤。
附上:
C語言的關鍵字共有32個,根據關鍵字的作用,可分其為數據類型關鍵字、控制語句關鍵字、存儲類型關鍵字和其它關鍵字四類。
1 數據類型關鍵字(12個):
(1) char :聲明字元型變數或函數
(2) double :聲明雙精度變數或函數
(3) enum :聲明枚舉類型
(4) float:聲明浮點型變數或函數
(5) int: 聲明整型變數或函數
(6) long :聲明長整型變數或函數
(7) short :聲明短整型變數或函數
(8) signed:聲明有符號類型變數或函數
(9) struct:聲明結構體變數或函數
(10) union:聲明聯合數據類型
(11) unsigned:聲明無符號類型變數或函數
(12) void :聲明函數無返回值或無參數,聲明無類型指針(基本上就這三個作用)
(2)控制語句關鍵字(12個):
A循環語句
(1) for:一種循環語句(可意會不可言傳)
(2) do :循環語句的循環體
(3) while :循環語句的循環條件
(4) break:跳出當前循環
(5) continue:結束當前循環,開始下一輪循環
B條件語句
(1)if: 條件語句
(2)else :條件語句否定分支(與 if 連用)
(3)goto:無條件跳轉語句
C開關語句
(1)switch :用於開關語句
(2)case:開關語句分支
(3)default:開關語句中的「其他」分支
D
return :子程序返回語句(可以帶參數,也看不帶參數)
3 存儲類型關鍵字(4個)
(1)auto :聲明自動變數 一般不使用
(2)extern:聲明變數是在其他文件正聲明(也可以看做是引用變數)
(3)register:聲明積存器變數
(4)static :聲明靜態變數
4 其它關鍵字(4個):
(1)const :聲明只讀變數
(2)sizeof:計算數據類型長度
(3)typedef:用以給數據類型取別名(當然還有其他作用
(4)volatile:說明變數在程序執行中可被隱含地改變
⑷ 編譯原理的實質
計算機程序編譯原理的實質就是把程序員員容易理解的高級語言程序代碼流翻譯成計算機可執行的機器指令代碼流。可以使用「一斷、二比、三譯」形象說明實質。
1、斷。按照語言的語法規則掃描斷詞,結合文法詞典把程序字元串流分解成為計算機語言能夠識別的基本單元(標識詞、運算符)。
2、比。從程序流中找出擴展標識詞的定義,建立標識詞結構,放入文法詞典,服務於新的定義和函數程序代碼的編譯。程序語句、表達式裡面使用的標識可以從詞典中比較找到。
3、譯。把函數程序文本字元串流中的算術表達式、賦值語句、控制語句翻譯成為計算機機器語言二進制代碼流。
4、組裝函數翻譯後的二進制代碼流,明確數據空間地址和大小,生成計算機裸機或操作系統可以執行目標代碼。
⑸ C 如何識別函數
#include <string.h>
#include <stdio.h>
//如果你用的是VC6,這個宏對於習慣標准語法的人很管用
#define for if(false);else for
// 這只是一個非常簡單的例子,具體你還是需要自己修改來滿足跟復制的需求
// 這個函數會直接修改tempstr,將字元串中的分隔符替換為\0
// tempstr:臨時字元串
// delimitChars:包含各種分隔字元的字元串
// tokens:用於接收分割後的字元串指針的數組
void strSplit(char * tempstr, const char *delimitChars, char *tokens[])
{
tokens[0]=NULL;
if(tempstr==NULL)
return;
tokens[0]=tempstr;
for(size_t pos=0,i=0;tempstr[pos]!='\0';)
{
tokens[i++]=tempstr+pos;
pos=pos+strcspn(tempstr+pos,delimitChars);
if(tempstr[pos]=='\0')
break;
tempstr[pos++]='\0';
}
}
int main()
{
//由於傳遞給strSplit的字元串必須是可修改的,所以這里將字元串存儲在字元數組中,注意這跟char *tempstr="123;34;;56"是不一樣的
char tempstr[100]="shiting;;pig";
//一個指針數組,用於存儲分割後的字元串指針
char* tokens[8]={};
//這個函數執行後,tempstr的內容被修改為"shiting\0\0pig"
//所以在必要的時候你應該傳遞一份拷貝給這個函數
strSplit(tempstr,";",tokens);
//列印分割後的字元串
for (int i=0;tokens[i]!=NULL;i++)
{
printf("%s\n",tokens[i]);
}
return 0;
}
⑹ 一直有個疑惑,C/C++編譯器是如何調用函數的
函數的調用就是 跳轉到函數體的入口地址。
函數體本身的存儲空間是在exe里txt段,然後運行載入的時候映射到地址空間。不過看你的問題,你關注的不是這個的佔用。
關於你問的問題, 其實是因為一旦定義了虛函數,在C++類型的頭部,就會有一個指針的隱藏變數被定義,從而該類型的每個對象都會有這個變數的大小。 這個只有類型有和沒有虛函數的區別,虛函數的個數造成內存增長只是虛表裡(每class一個),每個對象里只是存的一個指針,不會有size變化。
對於非虛的函數,編譯的時候,直接就是填寫的函數體的入口地址; 而虛函數,則是要經過計算,先通過對象頭部寸的虛表指針找到虛表,再去找對應的虛表項 ,裡面存儲的就是需要的函數的入口地址。
建議樓主看看 C++布局方面的書,比如 <Inside C++ Object Model>, 以及平時多用VS操練一下調試技巧,然後適當熟悉簡單的匯編代碼,對融會貫通很有幫助。
⑺ 優先函數是什麼編譯原理
構造算符優先分析表時使用的優先函數,其等價於矩陣表,但存儲量小。
定義兩個函數,其對應元素的值為優先值,通過循環比較各元素的兩個值,每次將優先順序大的值改為小的值+1,若相等則都賦為目前較大的值,循環直至結果沒有變化,構造OK
⑻ 如何用C語言識別一個C程序的注釋和函數
/* */ 主要是字元匹配的問題,檢索 / 和 * ,如果檢索到 * 和 / ,哨兵變數為 1 ,否則為 0 ;
//主要是檢索到 / 和 / 就可以,以後這一行都是注釋了。
頭一個注釋可以應用於 printf 中,後者不可以。
---------------------
以上均是個人理解,如有錯誤,請高手指正。