c函數編譯符號表
1. c語言程序編譯後產生哪些類型的文件這些文件的作用是什麼
1、以GCC編譯器為例,可以分為四步。
第一步是預處理,包括語法檢查等工作。
gcc
-P
abc.c
第二步由源程序生產匯編語言代碼。
gcc
-S
abc.c
會生成abc.s文件,這個文件里就是匯編代碼。
第三步編譯器生成目標代碼,一個源文件生成一個目標代碼。
gcc
-c
abc.c
會生成abc.o
第四步連接器從目標代碼生成可執行文件。
gcc
abc.o
2、目標代碼包括機器碼和符號表(函數及變數名)。連接器的主要作用是通過符號表在庫文件和其他模塊中找到在目標代碼中引入或未定義的符號(函數及變數名),將幾個目標代碼合成可執行文件。
2. 如何查看ndk編譯的動態庫符號表
$ /path/to/ndk/buid/prebuilt/windows/arm-eabi-4.4.0/bin/arm-eabi-nm libs/armeabi/libsanangeles.so
00003600 T java_com_example_SanAngeles_DemoGLSurfaceView_nativePause
00003638 T Java_com_example_SanAngeles_DemoRenderer_nativeDone
0000367c T Java_com_example_SanAngeles_DemoRenderer_nativeInit
000035b4 T Java_com_example_SanAngeles_DemoRenderer_nativeRender
00003644 T Java_com_example_SanAngeles_DemoRenderer_nativeResize
00007334 a _DYNAMIC
0000740c a _GLOBAL_OFFSET_TABLE_
復制代碼
    這里可以看到幾乎所有的函數名全局變數名都會被導出。其中有Java_com_example_SanAngeles_為前綴的JNI介面函數,有importGLInit這些普通函數,有freeGLObject這些局部(static)函數,還有sStartTick等全局變數名。其實在這個動態發布的時候,只需要導出java_com_開頭的jni函數就可以了,裡面這些細節函數名完全不需要暴露出來。
    如何做到這一點呢?首先,我們需要了解gcc新引進的選項-fvisibility=hidden,這個編譯選項可以把所有的符號名(包括函數名和全局變數名)都強制標記成隱藏屬性。我們可以在Android.mk中可以通過修改LOCAL_CFLAGS選項加入-fvisibility=hidden來做到這一點,這樣編譯之後的.so看到的符號表為:
000033d0 t Java_com_example_SanAngeles_DemoGLSurfaceView_nativePause
00003408 t Java_com_example_SanAngeles_DemoRenderer_nativeDone
0000344c t Java_com_example_SanAngeles_DemoRenderer_nativeInit
00003384 t Java_com_example_SanAngeles_DemoRenderer_nativeRender
00003414 t Java_com_example_SanAngeles_DemoRenderer_nativeResize
00007104 a _DYNAMIC
3. c語言程序的運行過程中在哪些過程中會產生文件
編譯過程會產生.o文件(目標文件)鏈接後產生可執行文件。
目標代碼包括機器碼和符號表(函數及變數名)。連接器的主要作用是通過符號表在庫文件和其他模塊中找到在目標代碼中引入或未定義的符號(函數及變數名),將幾個目標代碼合成可執行文件。
不同的系統,產生的文件不一樣;
win:
->.obj目標文件
->.obj目標文件->.exe可執行文件
->.rc

(3)c函數編譯符號表擴展閱讀:
解釋方式下,計算機對高級語言書寫的源程序一邊解釋一邊執行,不能形成目標文件和執行文件。
編譯方式下,首先通過一個對應於所用程序設計語言的編譯程序對源程序進行處理,經過對源程序的詞法分析、語法分析、語意分析、代碼生成和代碼優化等階段將所處理的源程序轉換為用二進制代碼表示的目標程序,通過連接程序處理將程序中所用的函數調用、系統功能調用等嵌入到目標程序中,構成一個可以連續執行的二進制執行文件。
調用這個執行文件就可以實現程序員在對應源程序文件中所指定的相應功能。
4. c語言編程
//計劃做的腳本引擎的一部分
//參考的 C++編程藝術
//總地來說會有一些難度
//我的是C++應該會給你一些啟發
//TypeDef.h
#include "windows.h"
#ifndef B_TYPE_DEF_H
#define B_TYPE_DEF_H
const int MAX_T_LEN  = 128;//可以分析的最大符號長度(同時決定了一個字元變數的最大長度為128位元組)
const int MAX_ID_LEN = 31;//允許的最大的標識長度(一個標識符是指一個變數名或函數名)
const int MAX_BUF_LEN = 1024;//解釋緩沖區1024位元組
const int NUM_PARAMS = 32;//最大參數數目
const int MAX_DIM_NUM = 65536//數組最大維數
//需要分析的所有東西
enum Token_Item { UNDEF=1, //未定義
    E_TEMP,//當模板使用 
    E_CHAR,//char關鍵字
 E_INT,//int關鍵字
 E_FLOAT,//float關鍵字
 E_SWITCH,//switch關鍵字 
    E_CASE,//case關鍵字
 E_IF,//if關鍵字
 E_ELSE,//else關鍵字
 E_FOR,//for關鍵字
 E_DO,//do關鍵字
 E_WHILE,//while關鍵字
 E_BREAK,//break關鍵字 
    E_RETURN,//return關鍵字
 E_COUT,//cout關鍵字
 E_CIN,//cin關鍵字
 LBLOCK, //{
 RBLOCK,//}
 DOU,//,
 EOS,//;
 MAO,//:
 SFEN,//'已舍棄,不含'分析
 LT,//<
 LE,//<=
 GT,//>
 GE,//>=
 EQ,//==
 NE,//!=
 FF,//.
 LK,//(
 NOT,//!
 INC,//++
 DEC,//--
 ADD,//+
 SUB,//-
 RK,//)
 LZK,//[
 RZK,//]
 LS,//<<
 RS,//>>
 ASS,//= 
 AND,//&&
 OR,//||
 MUL,//*
 DIV,///
 MOD,//%
 POW,//^
 NUMBER, //數字
 IDENTIFIER,//標識 
 STRING,//字元串
 END//文件結束
};//需要分析的全部符號
enum Token_Type{
 UNK,//未知類型
 KEY,//關鍵字
    FJF,//分界符
 CMP,//比較運算符
 OPE,//運算符
 NUM,//數字
 IDE,//標識符
 STR,//字元串
 NON,//結束符號
    UDF//未定義
};
typedef struct Token_Table{//符號表
 char name[MAX_T_LEN];
 Token_Item token;
 Token_Type type;
} TOKEN_TABLE,*PTOKEN_TABLE;
enum error_msg  //錯誤類型
     { SYNTAX=1000, NO_EXP, NOT_VAR, DUP_VAR, DUP_FUNC, 
       SEMI_EXPECTED, UNBAL_BRACES, FUNC_UNDEF, 
       TYPE_EXPECTED, RET_NOCALL, PAREN_EXPECTED, 
       WHILE_EXPECTED, QUOTE_EXPECTED, DIV_BY_ZERO, 
       BRACE_EXPECTED, COLON_EXPECTED,FAIL_OPEN,ERROR_SIZE,
    NO_MAIN,ERROR_ASSIGN,ERROR_RZK,ERROR_DIM}; 
 
class InterpExc { //錯誤類
  error_msg err; 
public: 
  InterpExc(error_msg e) { err = e; } 
  error_msg get_err() { return err; } 
}; 
enum Vars{類型
 V_Int,
 V_Float,
 V_String,
 V_pInt,
 V_pFloat,
 V_pString,
 V_Udef
};
#endif
#ifndef V_NULL
#define V_NULL (-1)
#endif
//Cfenxi.h
#include "TypeDef.h"
#include <iostream>
#include <vector>
#include <stack>
#include <algorithm>
#include <string>
using namespace std;
//Fenxi類說明
//curr_pt始終指向將要分析的地址
//prev_pt為前一個分析的地址
//可以使用函數GotoPt來改變當前分析地址
//分析結果放在變數stoken,item,type
//在Cfenxi.cpp中定義了一個文件級變數TOKEN_TABLE tokentable[];
//在使用的時候必須聲明這個變數
#ifndef B_CFENXI_H
#define B_CFENXI_H
class Fenxi{
public:
    char stoken[MAX_T_LEN+1];//分析出來的符號名
 char buff[MAX_BUF_LEN+1];//緩沖區
 Token_Item item;//分析出來的具體符號
 Token_Type type;//符號大類
 long curr_pt;//當前分析點
 long prev_pt;//前一個分析點
 char pFileName[256];//腳本文件名
 PTOKEN_TABLE pTokenTable;//符號表
public:
 Fenxi(){};
 ~Fenxi(){};
 void Create(char*,PTOKEN_TABLE,int);//創建分析對象
 void GetToken();//分析一步
 void GotoPt(long);//跳分析點
 void PutBack();//回退一個分析點
private:
 int  nTableItem;//分析表中的分析數目
 long iFileLength;//腳本文件長度
 int  iBlock;//當前所在區塊
 int  iYouBiao;//當前游標
 char cbuff;//當前所指向的字元
 char cbuff1;//超前搜索的字元
 void MoveNext();//向下移動
 void MovePrev();//向前移動
 void LoadBlock();//裝入一個塊
 long GetPt(int i,int n){return (long)(i*MAX_BUF_LEN+n);};//計算位置
 bool KeyLookUp(char*,Token_Item &);//查找是不是關鍵詞
 bool isdelim(char);
};
//解釋類
class var_value{
public:
 char string_value[MAX_T_LEN+1];
 int  int_value;
 float float_value;
 Vars v_type;
public:
 var_value()
 {
  int_value=0;
  float_value=0;
  string_value[0]=0;
  v_type=Udef;
 }
 var_value(const var_value&);
 set_type(Vars type){v_type=type;}
    ~var_value(){}
 friend bool operator == (const var_value& _X, const var_value& _Y);
 friend bool operator <  (const var_value& _X, const var_value& _Y);
};
class temp_var_value{
public:
 char string_value[MAX_T_LEN+1];
 int  int_value;
 float float_value;
 int  p_int;
 int  p_float;
 int  p_string;
 vector<int> dim;
 Vars v_type;
public:
 temp_var_value()
 {
  int_value=0;
  float_value=0;
  string_value[0]=0;
  p_int=p_float=p_string=V_NULL;
  v_type=Udef;
 };
 temp_var_value(const temp_var_value&);
 temp_set_type(Vars type){v_type=type;}
    ~temp_var_value(){}
 friend bool operator == (const temp_var_value& _X, const temp_var_value& _Y);
 friend bool operator <  (const temp_var_value& _X, const temp_var_value& _Y);
};
struct var_type { //變數類型
  char    var_name[MAX_ID_LEN+1]; // 變數名
  Vars    v_type;//數據類型
  vector<var_value> value; //變數值
  vector<int>  v_dim;//變數維數
  int    v_max;//變數的最大數目
};
 
struct func_type { 
  char func_name[MAX_ID_LEN+1]; //函數名
  Vars ret_type; //返回值類型 
  long loc; // 函數入口點,函數的入口點是指分析點指向函數括弧後第一個字元 
};
class Script{
public:
 Fenxi   theFx;//詞法分析對象,負責對腳本文件的操作
 char   FileName[256];//腳本文件名
 var_value  ret_value;//返回值
 bool   breakfound;//中斷
public:
 Script(){};
 ~Script(){};
    void Create(char*,PTOKEN_TABLE,int);//創建腳本對象
 void ExecuteScript();//開始解釋腳本
private:
 void PreScan();//預掃描
 void decl_global();//聲明全局變數
 long find_func(char*);//返回函數的入口點
    void    ItemToVar(Token_Item,Vars&);//根據一個項,得到相當的變數類型
 void CallFun();//執行一個函數
 void get_args();//得到函數的形式參數名
 void Interp();//具體解釋
private:
 void eval_exp (var_value &value); 
 void eval_exp0(var_value &value); 
 void eval_exp1(var_value &value); 
 void eval_exp2(var_value &value); 
 void eval_exp3(var_value &value); 
 void eval_exp4(var_value &value); 
 void eval_exp5(var_value &value); 
 void eval_exp6(var_value &value); 
 void eval_exp7(var_value &value); 
 void eval_exp8(var_value &value); 
 bool    is_var(char *s);
 // 變數名,變數的維數,變數的值,變數的類型
 void assign_var(char *var_name,int idx, var_value value);
 void find_var_value(char *var_name,int idx,var_value& value);
 int  find_idx(vector<int>,vector<int>);// 計算[][]
 void find_vector(vector<int> &);//讀取[]
 int  cal_idx(vector<int>);
 Vars is_var_type;//使用is_var的時候如果返回值是真那麼這個變數存儲了變數類型
public:
//每執行一個函數的時候就把進入前的局部變數數目
//放到函數結點棧,函數執行完的時候就根據棧里的
//數據改變局部函數表裡的變數,從而實現變數的靈活使用
//同理塊結點棧的原理也一樣
//變數表
vector<var_type>  global_vars; //全局變數表
vector<var_type>  local_var_stack; //局部變數表(函數參數作為局部變數處理) 
vector<func_type>  func_table; //函數表 
stack<int>    func_call_stack;//函數結點棧
stack<int>    nest_scope_stack;//塊結點棧
};
#endif
//Fenxi.cpp
#include "CFenxi.h"
#include  <cstring>
#include <cctype>
#include <fstream>
#include <cstdio>
#include <cmath>
using namespace std;
///////////////////////////////////////////////////////////////////////
/////////////////////////詞法分析類的函數定義//////////////////////////
///////////////////////////////////////////////////////////////////////
extern TOKEN_TABLE tokentable[]={
 "char",E_CHAR,KEY,
 "int",E_INT,KEY,
 "float",E_FLOAT,KEY,
 "switch",E_SWITCH,KEY,
 "case",E_CASE,KEY,
 "if",E_IF,KEY,
 "else",E_ELSE,KEY,
 "for",E_FOR,KEY,
 "do",E_DO,KEY,
 "while",E_WHILE,KEY,
 "break",E_BREAK,KEY,
 "return",E_RETURN,KEY,
 "cout",E_COUT,KEY,
 "cin",E_CIN,KEY,
 "{",LBLOCK,FJF,
 "}",RBLOCK,FJF,
 ",",DOU,FJF,
 ";",EOS,FJF,
 "<",LT,CMP,
 "<=",LE,CMP,
 ">",GT,CMP,
 ">=",GE,CMP,
 "==",EQ,CMP,
 "!=",NE,CMP,
 ".",FF,OPE,
 "(",LK,OPE,
 ")",RK,OPE,
 "[",LZK,OPE,
 "]",RZK,OPE,
 "++",INC,OPE,
 "--",DEC,OPE,
 "<<",LS,OPE,
 ">>",RS,OPE,
 "=",ASS,OPE,
 "!",NOT,OPE,
 "&&",AND,OPE,
 "||",OR,OPE,
 "+",ADD,OPE,
 "-",SUB,OPE,
 "*",MUL,OPE,
 "/",DIV,OPE,
 "%",MOD,OPE,
 "^",POW,OPE,
};
var_value::var_value(const var_value& p)
{
 int_value=p.int_value;
 float_value=p.float_value;
 strcpy(string_value,p.string_value);
 v_type=p.v_type;
}
bool operator == (const var_value& _X, const var_value& _Y)
{
 if (_X.v_type != _Y.v_type)
 {
  return false;
 }
 else
 {
  switch (_X.v_type)
  {
  case V_Float:
   return (abs(_X.float_value - _Y.float_value) < 0.0001);
   break;
  case V_Int:
   return (_X.int_value == _Y.int_value);
   break;
  case V_Int:
   return !(strcmp(_X.string_value, _Y.string_value));
   break;
  default:
   return false;
  }
 }
}
bool operator <  (const var_value& _X, const var_value& _Y)
{
 if (_X.v_type != _Y.v_type)
 {
  return false;
 }
 else
 {
  switch (_X.v_type)
  {
  case V_Float:
   return (_X.float_value < _Y.float_value);
   break;
  case V_Int:
   return (_X.int_value < _Y.int_value);
   break;
  case V_Int:
   return !(strcmp(_X.string_value, _Y.string_value));
   break;
  default:
   return false;
  }
 }
temp_var_value::temp_var_value(const temp_var_value& p)
{
 int_value=p.int_value;
 float_value=p.float_value;
 strcpy(string_value,p.string_value);
 p_int=p.p_int;
 p_float=p.p_float;
 p_string=p.p_string;
 v_type=p.v_type;
}
void Fenxi::Create(char* p,PTOKEN_TABLE ptt,int n)
{
 strcpy(pFileName,p);
 ifstream fin(pFileName,ios::in|ios::binary);
 fin.seekg(0,ios::end);
 iFileLength=fin.tellg();
    fin.close();
    if(iFileLength==0)
  throw InterpExc(ERROR_SIZE);
iBlock=0;
 LoadBlock();
 MoveNext();//指向第一個字元
 iYouBiao=0;//置游標於文件頭
 curr_pt=0;
 prev_pt=0;
 cbuff=buff[0];//當前應該分析字元
 cbuff1=buff[1];//超前搜索字元
 pTokenTable=ptt;
 nTableItem=n;//分析表設置
}
void Fenxi::MoveNext()
{
 if(iYouBiao==MAX_BUF_LEN-1)//如果當前游標在緩沖區尾
 {
  iBlock++;
  LoadBlock();
  cbuff=buff[0];
  cbuff1=buff[1];//超前搜索
 }
 else
 {
  iYouBiao++;
  cbuff=buff[iYouBiao];
  if(iYouBiao==MAX_BUF_LEN-1)//超前搜索
  {
       char temp[2];
    temp[1]=0;
    ifstream fin(pFileName,ios::in|ios::binary);
    fin.seekg(MAX_BUF_LEN*(iBlock+1));
    fin.read(temp,1);
    int i=fin.gcount();
    temp[i]=0;
    fin.close();
    cbuff1=temp[0];
  }
  else
  cbuff1=buff[iYouBiao+1];
 }
    
 curr_pt=GetPt(iBlock,iYouBiao);
}
void Fenxi::MovePrev()
{
 if(iYouBiao==0)//如果當前游標在緩沖區頭
 {
  cbuff1=cbuff;//超前搜索
  iBlock--;
  LoadBlock();
  iYouBiao=MAX_BUF_LEN-1;
  cbuff=buff[iYouBiao];
 }
 else
 {
  cbuff1=cbuff;//超前搜索
  iYouBiao--;
  cbuff=buff[iYouBiao];
 }
 curr_pt=GetPt(iBlock,iYouBiao);
}
void Fenxi::PutBack()
{
 GotoPt(prev_pt);
}
void Fenxi::LoadBlock()//裝入一個塊
{
 ifstream fin(pFileName,ios::in|ios::binary);
 fin.seekg(MAX_BUF_LEN*iBlock);
 fin.read(buff,MAX_BUF_LEN);
 int i=fin.gcount();
 buff[i]=0;
 iYouBiao=0;
 fin.close();
}
void Fenxi::GotoPt(long pt)
{
 if(pt/MAX_BUF_LEN==curr_pt/MAX_BUF_LEN)//如果是在同一個塊內的話
 {
  curr_pt=pt;
  iYouBiao=curr_pt-iBlock*MAX_BUF_LEN;
  cbuff=buff[iYouBiao];
 }
 else//否則要重新裝入內存
 {
  curr_pt=pt;
  iBlock=curr_pt/MAX_BUF_LEN;
  LoadBlock();
  iYouBiao=curr_pt-iBlock*MAX_BUF_LEN;
  cbuff=buff[iYouBiao];
 }
 if(iYouBiao==MAX_BUF_LEN-1)//超前搜索
 {
  char temp[2];
  temp[1]=0;
  ifstream fin(pFileName,ios::in|ios::binary);
  fin.seekg(MAX_BUF_LEN*(iBlock+1));
  fin.read(temp,1);
  int i=fin.gcount();
  temp[i]=0;
  fin.close();
  cbuff1=temp[0];
 }
 else
 cbuff1=buff[iYouBiao+1];
}
void Fenxi::GetToken() 
{ 
 
 prev_pt=curr_pt;//保存前一個的位置
  char *temp; //利用一個指針向字元里寫內容
  item=UNDEF;type=UDF;
 
  temp = stoken; 
  *temp = '\0'; 
  
  // 如果當前字元是空格且未到文件末 
  while(isspace(cbuff) && cbuff) MoveNext(); 
 
  // 跳過行 
  while(cbuff == '\r') { 
    MoveNext();
    MoveNext();
    while(isspace(cbuff) && cbuff) MoveNext(); 
  } 
 
  // 是否結尾
  if(cbuff == '\0') { 
    *stoken = '\0'; 
    item = END; 
 type=NON;
    return ; 
  } 
 
  // 檢查{}標識符
  if(strchr("{}", cbuff)) {  
stoken[0]=cbuff;
    stoken[1]='\0';
    type=FJF;
    if(cbuff=='{')
     item=LBLOCK;
       else
     item=RBLOCK;
 MoveNext();//指向下一個字元
    return ; 
  } 
  // 檢查注釋信息 
  if(cbuff == '/') 
    if(cbuff1 == '*') { // /*注釋符
      MoveNext();
   MoveNext();
      do { // 找到結尾 
        while(cbuff != '*') MoveNext(); 
        MoveNext(); 
      } while (cbuff != '/'); 
      MoveNext();  
   GetToken();
   return;
    } else if(cbuff1 == '/') { // is a // CMPment 
      MoveNext();
   MoveNext(); 
      // Find end of CMPment. 
      while(cbuff != '\r' && cbuff != '\0') MoveNext(); 
      if(cbuff == '\r') {MoveNext();MoveNext();} 
      GetToken();
   return;
    } 
 
  // 檢查雙操作符 
  if(strchr("!<>=+-&|", cbuff)) {  
    switch(cbuff) {
  case '|':
  if(cbuff1 == '|') { 
          MoveNext();MoveNext(); 
          *temp = '|'; 
          temp++; 
    *temp = '|';
     temp++; 
          *temp = '\0'; 
    item=OR;
    type=OPE;
        } 
        break;
   case '&':
  if(cbuff1 == '&') { 
          MoveNext();MoveNext(); 
          *temp = '&'; 
          temp++; 
    *temp = '&';
     temp++; 
          *temp = '\0'; 
    item=AND;
    type=OPE;
        } 
        break;
      case '=': 
        if(cbuff1 == '=') { 
          MoveNext();MoveNext(); 
          *temp = '='; 
          temp++; 
    *temp = '=';
     temp++; 
          *temp = '\0'; 
    item=EQ;
    type=CMP;
        } 
        break; 
      case '!': 
        if(cbuff1 == '=') { 
          MoveNext();MoveNext(); 
          *temp = '!'; 
          temp++; 
    *temp = '=';
     temp++; 
          *temp = '\0'; 
    item=NE;
    type=CMP; 
        } 
        break; 
      case '<': 
        if(cbuff1 == '=') { 
          MoveNext();MoveNext(); 
          *temp = '<'; 
          temp++; 
    *temp = '=';
    item=LE;
    type=CMP; 
        } 
        else if(cbuff1 == '<') { 
          MoveNext();MoveNext(); 
          *temp = '<'; 
          temp++; 
    *temp = '<';
    item=LS;
    type=OPE; 
        } 
        else { 
          MoveNext();
          *temp = '<'; 
    item=LT;
    type=CMP;
  } 
        temp++; 
        *temp = '\0'; 
        break; 
      case '>': 
        if(cbuff1 == '=') { 
          MoveNext();MoveNext(); 
          *temp = '>'; 
          temp++; 
    *temp = '=';
    item=GE;
    type=CMP;
        } else if(cbuff1 == '>') { 
          MoveNext();MoveNext(); 
          *temp = '>'; 
          temp++; 
    *temp = '>';
    item=RS;
    type=OPE; 
        } 
        else { 
          MoveNext();
          *temp = '>'; 
    item=GT;
    type=CMP; 
        } 
        temp++; 
        *temp = '\0'; 
        break; 
      case '+': 
        if(cbuff1 == '+') { 
          MoveNext();MoveNext(); 
          *temp = '+'; 
          temp++; 
    *temp = '+';
    temp++; 
    *temp = '\0';
    item=INC;
    type=OPE; 
        } 
        break; 
      case '-': 
        if(cbuff1 == '-') { 
          MoveNext();MoveNext(); 
          *temp = '-'; 
          temp++; 
    *temp = '-';
    temp++; 
    *temp = '\0';
    item=DEC;
    type=OPE;
        } 
        break; 
    } 
 
    if(*stoken) return; 
  } 
 
  // 其它運算符號 
  if(strchr("+-*^/=().[]|!%", cbuff)) { 
    type=OPE;
 switch(cbuff){
 case '+':
  item=ADD;break;
 case '-':
  item=SUB;break;
 case '*':
  item=MUL;break;
 case '/':
  item=DIV;break;
 case '=':
  item=ASS;break;
 case '(':
  item=LK;break;
 case ')':
  item=RK;break;
 case '[':
  item=LZK;break;
 case ']':
  item=RZK;break;
 case '.':
  item=FF;break;
 case '|':
  item=UNDEF;type=UDF;break;
 case '!':
  item=NOT;break;
 case '%':
  item=MOD;break;
 }
 *temp = cbuff; 
    MoveNext(); 
    temp++; 
    *temp = '\0'; 
    return ; 
  } 
    // 分界符號 
  if(strchr(";,#:", cbuff)) { 
 type=FJF;
 switch(cbuff){
 case ';':
  item=EOS;break;
 case ',':
  item=DOU;break;
 case ':':
  item=MAO;break;
 }
 *temp = cbuff; 
    MoveNext(); 
    temp++; 
    *temp = '\0'; 
    return ;
  }
 
  // 讀取一個字元串
  if(cbuff == '"') { 
    MoveNext(); 
    while(cbuff != '"' && cbuff != '\r' && cbuff) { 
      // Check for \n escape sequence. 
      if(cbuff == '\\') { 
        if(cbuff1 == 'n') { 
          MoveNext(); 
          *temp++ = '\n'; 
        } 
      } 
      else if((temp - stoken) < MAX_T_LEN)  
        *temp++ = cbuff; 
 
      MoveNext(); 
    } 
    if(cbuff == '\r' || cbuff == 0) 
      throw InterpExc(SYNTAX); 
    MoveNext(); *temp = '\0'; 
    item=STRING;
 type=STR;
    return ; 
  } 
  // 讀取一個數字
  if(isdigit(cbuff)) { 
    while((cbuff>='0'&&cbuff<='9')||(cbuff=='.')) { 
      if((temp - stoken) < MAX_T_LEN)  
        *temp++ = cbuff; 
      MoveNext(); 
    } 
    *temp = '\0'; 
 item=NUMBER;
 type=NUM;
    return ; 
  } 
 
  // Read identifier or keyword. 
  if(isalpha(cbuff)) { 
    while(!isdelim(cbuff)) { 
      if((temp - stoken) < MAX_T_LEN)  
        *temp++ = cbuff; 
      MoveNext(); 
    } 
    item=E_TEMP; 
  } 
 
  *temp = '\0'; 
 
  // Determine if token is a keyword or identifier. 
  if(item == E_TEMP) {  // convert to internal form 
    if(KeyLookUp(stoken,item)) type=KEY; // is a keyword 
    else {type = IDE;item=IDENTIFIER;}
  } 
  if(type==UDF) 
    throw InterpExc(SYNTAX);
 
}
bool Fenxi::KeyLookUp(char *s,Token_Item &it){
  int i; 
//  char *p; 
 
  // 轉為小寫字母
 // p = s; 
 // while(*p) { *p = tolower(*p); p++; } 
  
  for(i=0; i<nTableItem; i++) { 
   if((tokentable[i].type==KEY)&&!strcmp(tokentable[i].name, s)) 
   {
    it=tokentable[i].token;
          return true; 
   }
  } 
 
  return false; 
} 
 // 符號檢查
bool Fenxi::isdelim(char c) 
{ 
  if(strchr(" !:;,+-<>/*^=().|&[]\"%", c) || c == 9 || 
     c == '\r' || c == 0) return true; 
  return false; 
}
5. c語言中「\」後加數字各是什麼
一般是轉義字元。
轉義字元是C語言中表示字元的一種特殊形式。轉義字元以反斜''開頭,後面跟一個字元或一個八進制或十六進制數表示。轉義字元具有特定的含義,不同於字元原有的意義,故稱轉義字元。示例如下:
charc1=''';//後面接一個特殊字元
charc2='110';//後面接一個三位的八進制數
charc3='x0d';//後面接一個兩位的十六進制數
6. C/C++問題,數組問題,菜鳥求教,望高手指教:
第一個問題:當然是內存中。CPU中能夠存儲信息的只有相應的寄存器,其存儲位數有限,但是存取速度極快(對CPU來說就是自己家的東西,可以信手拈來)。所以一般的分配沒有特殊說明都是在內存中(仔細追究起來實在內存空間中的棧空間中。當然利用new,malloc,alloc等申請的就在堆中——其實也是內存中的一部分,可參考有關操作系統的書籍)。
第二個問題:內存的分配最後都是有操作系統來完成的。當然也需要用到MMU的配合。
第三、四問題:C++中規定定義數組時,數組的大小必須是一個常數,或者一個常量表達式(如3+4)等,常量表達式在編譯階段,編譯器就能夠計算出其結果,從而在編譯過程中就能夠將大小,如本題中的30,告知操作系統,來申請合適的內存大小。如果你非要細究系統是怎樣識別的,這個問題可就有的探討了。每一種編譯器的識別方式不太一樣,有的是在數組前開辟一個空間,(如32位機子,開辟4位元組空間)來記錄數組的大小,從而告知編譯器;有的則是在數組連續空間結尾處設定分割位元組(如在VC調試狀態下的:0xcd、0xCC等位元組)。總之肯定需要一定的方式告知計算機數組的大小。
第五題:這個要糾結到strlen函數的設置問題上了,strlen默認的終止符號式『\0』,所以由於你的數組沒有初始化,你每次編譯的時候出現的結果很可能不同,(如果程序沒有大的修改,每次編譯結果很可能相同,你可以通過修改release和debug模式,;來迫使系統重新分配一下空間,來看一下,結果肯定是不一樣的)。
希望對你有一些提示。
可以參考相關的書籍《操作系統》《C++反匯編與逆向技術分析》等
