1.簡介
相對於py文件來說,編譯成pyc和pyo本質上和py沒有太大區別,只是對於這個模塊的載入速度提高了,並沒有提高代碼的執行速度,通常情況下不用主動去編譯pyc文件,除非需要商業提供,防止源代碼泄露。
(1)什麼是pyc文件
pyc是一種二進制文件,是由py文件經過編譯後,生成的文件,是一種byte code,py文件變成pyc文件後,載入的速度有所提高,而且pyc是一種跨平台的位元組碼,是由Python的虛擬機來執行的,這個是類似於java虛擬機的概念。pyc的內容,是跟python的版本相關的,不同版本編譯後的pyc文件是不同的,2.5編譯的pyc文件,2.4版本的python是無法執行的。
(2)什麼是pyo文件
pyo是優化編譯後的程序 python -O 源文件即可將源程序編譯為pyo文件
把需要的模塊編譯成pyo文件可以減少容量
2.反編譯
將python文件編譯為pyc文件(使用compileall 命令),再刪除源代碼。
(該文件類似於java中的class文件,但是我們使用的2.7版本的python,目前沒有
免費版的反編譯工具,所以目前要破解不是很容易,所以可以不必再做混淆)
(1)命令行編譯方法:
python -m compileall src/
echo compile finished...
rm -rf src/*.py
編譯成pyo的話:
就是在控制台執行 python -O -m py_compile file.py
(2)python程序編譯方法:
如果需要特殊的單獨編譯,則只需要使用py_complie這個模塊就行了,如下
import py_compile
py_compile.compile(r'H:\game\test.py')
反編譯工具:
1.uncompyle2 只能編譯2.7
反編譯Demo代碼:
import os
import sys
def displayFile(file):
unPath= sys.executable
unPath=unPath[ 0 : unPath.rfind( os.sep ) ]
newname = file[0:file.rfind('.')] + '.py'
command = "python -u "+unPath+"\scripts\uncompyle2 " + file + ">" + newname
try:
os.system(command)
except e:
print file
if __name__ == '__main__':
#print unPath
print 'init'
displayFile('E:\\test.pyc')
print 'finished'
2.zrax/pycdc 可以編譯3.0
Ⅱ PROC預編譯程序是什麼東西
要學Pro*c/c++,它是在c和c++裡面嵌套sql和pl/sql的語言
用文本編輯器,如uedit編輯,通過PROC預編譯程序編譯成c,c++源代碼,再通過c,c++的編譯工具編譯成可執行文件,可是PROC預編譯程序。
Ⅲ c語言程序,預編譯的作用是什麼
預編譯又稱為預處理 , 是做些代碼文本的替換工作。
處理 # 開頭的指令 ,
比如拷貝 #include 包含的文件代碼,
#define 宏定義的替換 , 條件編譯等,
就是為編譯做的預備工作的階段,主要處理#開始的預編譯指令,預編譯指令指示了在程序正式編譯前就由編譯器進行的操作,可以放在程序中的任何位置。
c 編譯系統在對程序進行通常的編譯之前,先進行預處理。 c 提供的預處理功能主要有以下三 種:
1)宏定義 #definemin(a,b)((a)>(b)?(b)::(a))
2 )文件包含 如:#include<stdio.h>
3 )條件編譯#ifndefGRAPHICS_H
#defineGRAPHICS_H
*****
#endif
#ifdefGRAPHICS_H
*****
#else
*****
#endif
Ⅳ C語言:預編譯是什麼
預編譯,顧名思義,從字面上看,就是提前編譯,它做的是工作就是為正式編譯做准備
它說處理的是有#標識的代碼,如講include的文件進行拷貝、#define的條件編譯等等!關於預編譯的介紹你可以到網路里進行查看,裡面有詳細的介紹!http://ke..com/view/176610.htm
Ⅳ 預處理命令的宏定義
1.不帶參數的宏定義:
宏定義又稱為宏代換、宏替換,簡稱「宏」。
格式:
#define標識符文本
其中的標識符就是所謂的符號常量,也稱為「宏名」。
預處理(預編譯)工作也叫做宏展開:將宏名替換為文本(這個文本可以是字元串、可以是代碼等)。
掌握宏概念的關鍵是「換」。一切以換為前提、做任何事情之前先要換,准確理解之前就要「換」。
即在對相關命令或語句的含義和功能作具體分析之前就要換:
例:
#define PI 3.1415926
把程序中全部的標識符PI換成3.1415926
說明:
(1)宏名一般用大寫
(2)使用宏可提高程序的通用性和易讀性,減少不一致性,減少輸入錯誤和便於修改。例如:數組大小常用宏定義
(3)可以用#undef命令終止宏定義的作用域
(4)宏定義可以嵌套
2.帶參數的宏:
除了一般的字元串替換,還要做參數代換
格式:
#define 宏名(參數表)文本
例如:#define S(a,b) a*b
area=S(3,2);第一步被換為area=a*b; ,第二步被換為area=3*2;
類似於函數調用,有一個啞實結合的過程:
(1)實參如果是表達式容易出問題
#define S(r) r*r
area=S(a+b);第一步換為area=r*r;,第二步被換為area=a+b*a+b;
正確的宏定義是#define S(r) ((r)*(r))
(2)宏名和參數的括弧間不能有空格
(3)宏替換只作替換,不做計算,不做表達式求解
(4)函數調用在編譯後程序運行時進行,並且分配內存。宏替換在編譯前進行,不分配內存
(5)宏的啞實結合不存在類型,也沒有類型轉換。
(6)宏展開使源程序變長,函數調用不會
(7)宏展開不佔運行時間,只佔編譯時間,函數調用占運行時間(分配內存、保留現場、值傳遞、返回值)
Ⅵ 程序語言最終怎樣被轉換成計算機能讀懂的機械語言,0和1,
程序語言有很多,拿最常用的c/c++語言舉例。
將用戶的文本形式的源代碼轉化成計算機可以直接執行的機器代碼的過程。主要經過這么幾個過程:
一、預編譯,又稱為預處理 , 是做些代碼文本的替換工作
二、編譯,由編譯器將c源代碼(.cpp)轉變成匯編代碼(.s)
三、匯編,由匯編器將匯編代碼(.s)轉變成目標代碼(.o)
四、鏈接,由鏈接器將代碼在執行過程用到的其他目標代碼和庫文件鏈接成為一個可執行程序也就是目標程序。
經過以上步驟高級語言就會被解釋成為計算機可以認知的機器語言。
一、預編譯
1、定義
處理以# 開頭的指令 , 比如拷貝 #include 包含的文件代碼,#define 宏定義的替換 , 條件編譯等,就是為編譯做的預備工作的階段。
主要處理#開始的預編譯指令,預編譯指令指示了在程序正式編譯前就由編譯器進行的操作,可以放在程序中的任何位置。
二、編譯
1、定義
編譯的過程就是將源代碼文件以字元流的形式進行處理,進行詞法和語法的分析,然後通過匯編器將源代碼指令轉變成匯編指令,編譯的過程包括兩個大部分:預處理 = 預編譯
2、特殊符號
特殊符號是指:例如在源程序中出現的LINE標識將被解釋為當前行號(十進制數),FILE則被解釋為當前被編譯的C源程序的名稱。預編譯程序對於在源程序中出現的這些串將用合適的值進行替換。
三、匯編
1、定義
匯編過程實際上是把匯編語言代碼翻譯成目標機器指令的過程。對於被翻譯系統處理的每一個C語言源程序,都將最終經過這一處理而得到相應的目標文件。目標文件中所存放的也就是與源程序等效的目標的機器語言代碼。
四、鏈接
1、定義
由匯編程序生成的目標文件並不能立即就被執行,其中可能還有許多沒有解決的問題。
Ⅶ 什麼是預編譯,何時需要預編譯
預編譯又稱為預處理,是做些代碼文本的替換工作
預編譯又稱為預處理,是做些代碼文本的替換工作
處理#開頭的指令,比如拷貝#include包含的文件代碼,#define宏定義的替換,條件編譯等
就是為編譯做的預備工作的階段
主要處理#開始的預編譯指令
預編譯指令指示了在程序正式編譯前就由編譯器進行的操作,可以放在程序中的任何位置。常見的預編譯指令有:
(1)#include 指令
該指令指示編譯器將xxx.xxx文件的全部內容插入此處。若用<>括起文件則在系統的INCLUDE目錄中尋找文件,若用" "括起文件則在當前目錄中尋找文件。一般來說,該文件是後綴名為"h"或"cpp"的頭文件。
注意:<>不會在當前目錄下搜索頭文件,如果我們不用<>而用""把頭文件名擴起,其意義為在先在當前目錄下搜索頭文件,再在系統默認目錄下搜索。
(2)#define指令
該指令有三種用法:
第一種是定義標識,標識有效范圍為整個程序,形如#define XXX,常與#if配合使用;
第二種是定義常數,如#define max 100,則max代表100(這種情況下使用const定義常數更好,原因見注1);
第三種是定義"函數",如#define get_max(a, b) ((a)>(b)?(a):(b)) 則以後使用get_max(x,y)就可以得到x和y中較大的數(這種方法存在一些弊病,見注2)。
第四種是定義"宏函數",如#define GEN_FUN(type) type max_##type(type a,type b){return a>b?a:b;} ,使用時,用GEN_FUN(int),則此處預編譯後就變成了 max_int(int a,int b){return a>b?a:b;},以後就可以使用max_int(x,y)就可以得到x和y中較大的數.比第三種,增加了類型的說明。
(3)#if、#else和#endif指令
這些指令一般這樣配合使用:
#if defined(標識) //如果定義了標識
要執行的指令
#else
要執行的指令
#endif
在頭文件中為了避免重復調用(比如說兩個頭文件互相包含對方),常採用這樣的結構:
#if !(defined XXX) //XXX為一個在你的程序中唯一的標識符,
//每個頭文件的標識符都不應相同。
//起標識符的常見方法是若頭文件名為"abc.h"
//則標識為"abc_h"
#define XXX
真正的內容,如函數聲明之類
#endif
Ⅷ #define SQR(X) (x)*(x) void main() { int a=16,k=2,m=1; a/=SQR(k+m)/SQR(k+m); printf("%d",a)
注意,#define做的僅僅是文本替換工作,是預編譯階段完成的,不可將其作為函數使用。
因而,在預編譯時所有的SQR(x)將被替換為(x)*(x)。故真正編譯的代碼為:
void main()
{
int a=16,k=2,m=1;
a/=(k+m)*(k+m)/(k+m)*(k+m); //k+m=3
printf("%d",a);
}按照四則運演算法則,3*3/3*3=9
故a/=9,16/9=1.
Ⅸ 編譯原理
C語言編譯過程詳解
C語言的編譯鏈接過程是要把我們編寫的一個C程序(源代碼)轉換成可以在硬體上運行的程序(可執行代碼),需要進行編譯和鏈接。編譯就是把文本形式源代碼翻譯為機器語言形式的目標文件的過程。鏈接是把目標文件、操作系統的啟動代碼和用到的庫文件進行組織形成最終生成可執行代碼的過程。過程圖解如下:
從圖上可以看到,整個代碼的編譯過程分為編譯和鏈接兩個過程,編譯對應圖中的大括弧括起的部分,其餘則為鏈接過程。
一、編譯過程
編譯過程又可以分成兩個階段:編譯和匯編。
1、編譯
編譯是讀取源程序(字元流),對之進行詞法和語法的分析,將高級語言指令轉換為功能等效的匯編代碼,源文件的編譯過程包含兩個主要階段:
第一個階段是預處理階段,在正式的編譯階段之前進行。預處理階段將根據已放置在文件中的預處理指令來修改源文件的內容。如#include指令就是一個預處理指令,它把頭文件的內容添加到.cpp文件中。這個在編譯之前修改源文件的方式提供了很大的靈活性,以適應不同的計算機和操作系統環境的限制。一個環境需要的代碼跟另一個環境所需的代碼可能有所不同,因為可用的硬體或操作系統是不同的。在許多情況下,可以把用於不同環境的代碼放在同一個文件中,再在預處理階段修改代碼,使之適應當前的環境。
主要是以下幾方面的處理:
(1)宏定義指令,如 #define a b。
對於這種偽指令,預編譯所要做的是將程序中的所有a用b替換,但作為字元串常量的 a則不被替換。還有 #undef,則將取消對某個宏的定義,使以後該串的出現不再被替換。
(2)條件編譯指令,如#ifdef,#ifndef,#else,#elif,#endif等。
這些偽指令的引入使得程序員可以通過定義不同的宏來決定編譯程序對哪些代碼進行處理。預編譯程序將根據有關的文件,將那些不必要的代碼過濾掉
(3) 頭文件包含指令,如#include "FileName"或者#include <FileName>等。
在頭文件中一般用偽指令#define定義了大量的宏(最常見的是字元常量),同時包含有各種外部符號的聲明。採用頭文件的目的主要是為了使某些定義可以供多個不同的C源程序使用。因為在需要用到這些定義的C源程序中,只需加上一條#include語句即可,而不必再在此文件中將這些定義重復一遍。預編譯程序將把頭文件中的定義統統都加入到它所產生的輸出文件中,以供編譯程序對之進行處理。包含到C源程序中的頭文件可以是系統提供的,這些頭文件一般被放在/usr/include目錄下。在程序中#include它們要使用尖括弧(<>)。另外開發人員也可以定義自己的頭文件,這些文件一般與C源程序放在同一目錄下,此時在#include中要用雙引號("")。
(4)特殊符號,預編譯程序可以識別一些特殊的符號。
例如在源程序中出現的LINE標識將被解釋為當前行號(十進制數),FILE則被解釋為當前被編譯的C源程序的名稱。預編譯程序對於在源程序中出現的這些串將用合適的值進行替換。
預編譯程序所完成的基本上是對源程序的「替代」工作。經過此種替代,生成一個沒有宏定義、沒有條件編譯指令、沒有特殊符號的輸出文件。這個文件的含義同沒有經過預處理的源文件是相同的,但內容有所不同。下一步,此輸出文件將作為編譯程序的輸出而被翻譯成為機器指令。
第二個階段編譯、優化階段。經過預編譯得到的輸出文件中,只有常量;如數字、字元串、變數的定義,以及C語言的關鍵字,如main,if,else,for,while,{,}, +,-,*,\等等。
編譯程序所要作得工作就是通過詞法分析和語法分析,在確認所有的指令都符合語法規則之後,將其翻譯成等價的中間代碼表示或匯編代碼。
優化處理是編譯系統中一項比較艱深的技術。它涉及到的問題不僅同編譯技術本身有關,而且同機器的硬體環境也有很大的關系。優化一部分是對中間代碼的優化。這種優化不依賴於具體的計算機。另一種優化則主要針對目標代碼的生成而進行的。
對於前一種優化,主要的工作是刪除公共表達式、循環優化(代碼外提、強度削弱、變換循環控制條件、已知量的合並等)、復寫傳播,以及無用賦值的刪除,等等。
後一種類型的優化同機器的硬體結構密切相關,最主要的是考慮是如何充分利用機器的各個硬體寄存器存放的有關變數的值,以減少對於內存的訪問次數。另外,如何根據機器硬體執行指令的特點(如流水線、RISC、CISC、VLIW等)而對指令進行一些調整使目標代碼比較短,執行的效率比較高,也是一個重要的研究課題。
2、匯編
匯編實際上指把匯編語言代碼翻譯成目標機器指令的過程。對於被翻譯系統處理的每一個C語言源程序,都將最終經過這一處理而得到相應的目標文件。目標文件中所存放的也就是與源程序等效的目標的機器語言代碼。目標文件由段組成。通常一個目標文件中至少有兩個段:
代碼段:該段中所包含的主要是程序的指令。該段一般是可讀和可執行的,但一般卻不可寫。
數據段:主要存放程序中要用到的各種全局變數或靜態的數據。一般數據段都是可讀,可寫,可執行的。
UNIX環境下主要有三種類型的目標文件:
(1)可重定位文件
其中包含有適合於其它目標文件鏈接來創建一個可執行的或者共享的目標文件的代碼和數據。
(2)共享的目標文件
這種文件存放了適合於在兩種上下文里鏈接的代碼和數據。
第一種是鏈接程序可把它與其它可重定位文件及共享的目標文件一起處理來創建另一個 目標文件;
第二種是動態鏈接程序將它與另一個可執行文件及其它的共享目標文件結合到一起,創建一個進程映象。
(3)可執行文件
它包含了一個可以被操作系統創建一個進程來執行之的文件。匯編程序生成的實際上是第一種類型的目標文件。對於後兩種還需要其他的一些處理方能得到,這個就是鏈接程序的工作了。
二、鏈接過程
由匯編程序生成的目標文件並不能立即就被執行,其中可能還有許多沒有解決的問題。
例如,某個源文件中的函數可能引用了另一個源文件中定義的某個符號(如變數或者函數調用等);在程序中可能調用了某個庫文件中的函數,等等。所有的這些問題,都需要經鏈接程序的處理方能得以解決。
鏈接程序的主要工作就是將有關的目標文件彼此相連接,也即將在一個文件中引用的符號同該符號在另外一個文件中的定義連接起來,使得所有的這些目標文件成為一個能夠被操作系統裝入執行的統一整體。
根據開發人員指定的同庫函數的鏈接方式的不同,鏈接處理可分為兩種:
(1)靜態鏈接
在這種鏈接方式下,函數的代碼將從其所在地靜態鏈接庫中被拷貝到最終的可執行程序中。這樣該程序在被執行時這些代碼將被裝入到該進程的虛擬地址空間中。靜態鏈接庫實際上是一個目標文件的集合,其中的每個文件含有庫中的一個或者一組相關函數的代碼。
(2) 動態鏈接
在此種方式下,函數的代碼被放到稱作是動態鏈接庫或共享對象的某個目標文件中。鏈接程序此時所作的只是在最終的可執行程序中記錄下共享對象的名字以及其它少量的登記信息。在此可執行文件被執行時,動態鏈接庫的全部內容將被映射到運行時相應進程的虛地址空間。動態鏈接程序將根據可執行程序中記錄的信息找到相應的函數代碼。
對於可執行文件中的函數調用,可分別採用動態鏈接或靜態鏈接的方法。使用動態鏈接能夠使最終的可執行文件比較短小,並且當共享對象被多個進程使用時能節約一些內存,因為在內存中只需要保存一份此共享對象的代碼。但並不是使用動態鏈接就一定比使用靜態鏈接要優越。在某些情況下動態鏈接可能帶來一些性能上損害。
我們在linux使用的gcc編譯器便是把以上的幾個過程進行捆綁,使用戶只使用一次命令就把編譯工作完成,這的確方便了編譯工作,但對於初學者了解編譯過程就很不利了,下圖便是gcc代理的編譯過程:
從上圖可以看到:
預編譯
將.c 文件轉化成 .i文件
使用的gcc命令是:gcc –E
對應於預處理命令cpp
編譯
將.c/.h文件轉換成.s文件
使用的gcc命令是:gcc –S
對應於編譯命令 cc –S
匯編
將.s 文件轉化成 .o文件
使用的gcc 命令是:gcc –c
對應於匯編命令是 as
鏈接
將.o文件轉化成可執行程序
使用的gcc 命令是: gcc
對應於鏈接命令是 ld
總結起來編譯過程就上面的四個過程:預編譯、編譯、匯編、鏈接。了解這四個過程中所做的工作,對我們理解頭文件、庫等的工作過程是有幫助的,而且清楚的了解編譯鏈接過程還對我們在編程時定位錯誤,以及編程時盡量調動編譯器的檢測錯誤會有很大的幫助的。
是否可以解決您的問題?
Ⅹ 編譯和預編譯有什麼區別。
預編譯又稱為預處理,是做些代碼文本的替換工作。
處理#開頭的指令,比如拷貝#include包含的文件代碼,#define宏定義的替換,條件編譯等
就是為編譯做的預備工作的階段
主要處理#開始的預編譯指令
編譯(compilation , compile) 1、利用編譯程序從源語言編寫的源程序產生目標程序的過程。 2、用編譯程序產生目標程序的動作。 編譯就是把高級語言變成計算機可以識別的2進制語言,計算機只認識1和0,編譯程序把人們熟悉的語言換成2進制的。