導航:首頁 > 源碼編譯 > rust編譯後小嗎

rust編譯後小嗎

發布時間:2022-07-26 19:52:22

A. 我為什麼要選擇Rust

你好,很高興為你解答。
專訪資深程序員庄曉立:我為什麼要選擇Rust?
Rust是由Mozilla開發的注重安全、性能和並發性的編程語言。這門語言自推出以來就得到了國內外程序員的大力推崇。Rust聲稱解決了傳統C語言和C++語言幾十年來飽受責難的內存安全問題,同時還保持了極高的運行效率、極深的底層控制、極廣的應用范圍。但在國內有關Rust的學習文檔並不多見,不久前,筆者聯繫上了Rust1.0版本代碼貢獻者庄曉立(精彩博文:為什麼我說Rust是靠譜的編程語言),請他分享Rust語言特性以及學習經驗。
CSDN:你是從什麼時候開始接觸Rust語言的?是什麼地方吸引了你?

庄曉立:我大概從2013年後半年開始深入接觸Rust語言。它居然聲稱解決了傳統C語言和C++語言幾十年來飽受責難的內存安全問題,同時還保持了極高的運行效率、極深的底層控制、極廣的應用范圍。

其ownership機制令人眼前一亮,無虛擬機(VM)、無垃圾收集器(GC)、無運行時(Runtime)、無空指針/野指針/內存越界/緩沖區溢出/段錯誤、無數據競爭(Data Race)……所有這些,都深深地吸引了我——這個十多年以來深受C語言折磨的痛並快樂著的程序員。

CSDN:在你看來,Rust是怎樣的一門語言?它適合開發什麼類型的項目?為何你會說Rust不懼怕任何競爭對手,它既能取代C語言地位;又可挑戰C++市場,還可向javapython分一杯羹?與這些語言相比,Rust有哪些優越的特性?

庄曉立:Rust是一門系統編程語言,特別適合開發對CPU和內存佔用十分敏感的系統軟體,例如虛擬機(VM)、容器(Container)、資料庫/游戲/網路伺服器、瀏覽器引擎、模擬器等,而這些向來主要都是C/C++的傳統領地。

此外,Rust在系統底層開發領域,如裸金屬(bare metal)、操作系統(OS)、內核(kernel)、內核模塊(mod)等,也有強勁的實力,足以挑戰此領域的傳統老大C語言。Rust豐富的語言特性、先進的設計理念、便捷的項目管理,令它在上層應用開發中也能大展拳腳,至少在運行性能上比帶VM和GC的語言要更勝一籌。無GC實現內存安全機制、無數據競爭的並發機制、無運行時開銷的抽象機制,是Rust獨特的優越特性。

其他語言很難同時實現這些目標,例如傳統C/C++無法保證內存安全,Java/Python等無法消除運行時開銷。但Rust畢竟還是很年輕的項目,它釋放影響力需要時間,被世人廣泛接受需要時間;它的潛力能否爆發出來,需要時間去檢驗。我們只需耐心等待。

CSDN:Rust在國內有沒有具體的實際使用案例?

庄曉立:因為Rust1.0正式版剛剛發布不足一月,在國內影響力還不大,我們不能苛求它在國內有實際應用案例。但是在國外,一兩年前就已經有OpenDNS和Skylight把Rust應用在生產環境。還有瀏覽器引擎Servo、Rust編譯器和標准庫、項目管理器Cargo等「兩個半大型應用案例」。這些足夠說明Rust語言的成熟和實用。

CSDN:你參與了Rust1.0版本代碼貢獻,目前該版本正式版已經發布,對此你感覺如何?這門語言是否已經達到比較成熟的階段?

庄曉立:我積極參與了Rust語言開源項目,多次貢獻源代碼,曾連續三次出現在Rust官方博客公布的Rust 1.0 alpha、Rust 1.0 beta和Rust 1.0正式版的貢獻者名單中。在Rust 1.0正式版出台的過程中及此前的很長一段時間,開發者付出了極大的努力,確保Rust 1.0正式版在Semver 2.0規范下,務必保持向後兼容性,除非遇到重大Bug不得不修復。

我認為,在1.0正式發布之後,Rust就已經進入了比較成熟的階段。而且,Rust還在快速迭代發展過程中,1.0發布6周後將發布1.1,再6周後將發布1.2,必然會一步一個台階,越來越成熟穩定。

CSDN:除了功能優先順序以外,在你看來,Rust正在朝什麼方向發展?未來的Rust可以期待什麼樣的特性?

庄曉立:Rust一定會沿著「確保內存安全、無運行開銷、高效實用」的既定方向持續發展。在短期內值得期待的語言特性有:動態Drop、偏特化、繼承、改進borrow checker、改進宏和語法擴展。短期內值得期待的其他特性有:增強文件系統API、提供內存申請釋放API、更好地支持Windows和ARM、更快的編譯速度、更方便的二進制分發機制(MUSL)、更實用的工具等等。

CSDN:據我了解,你之前也比較推崇Go語言,為何想到放棄Go轉向Rust?

庄曉立:推崇Go語言還談不上,不過我曾經嘗試努力接受Go語言,2011底年開始我曾經花費將近半年時間深度關注Go開發進程,提了很多具體的改進意見和建議,也曾經多次嘗試貢獻源代碼。後來考慮到Go語言的設計理念跟我偏差太大,其社區也不太友好,慢慢地疏遠了它。我曾經寫過一篇博客《我為什麼放棄Go語言》,談到了很多具體的原因。

CSDN:國內,參與Rust代碼貢獻的開發者多嗎?有核心的人員嗎?有哪些社區在維護Rust?

庄曉立:國內參與Rust代碼貢獻的開發者並不多,但也不少,官方的貢獻者名單中也偶見幾個貌似國人的名字。Rust的核心開發人員基本上都是Mozilla公司的員工,他們專職負責開發維護Rust語言和相關的項目,Rust社區也主要是他們參與組織和管理的。社區人員討論主要集中在GitHub項目主頁RFC/PR/Issue官方、Discuss論壇/IRC、Reddit、HN、StackOverflow等。

B. 怎樣看待 Mozilla 發布的 Rust 語言

rust 的開發推進非常有節奏,說每三個月發布一個版本,基本上都非常准時地做到了,road map 里定好的東西,都按時按質按量出現了,體現了良好的工程管理;從這一點上,這幾年出現的新語言鮮有管理得這么好的,有充分的理由讓大家相信 rust 的前景:一切都會有的。

rust 原是一個 servo 的子項目,它的發展是 servo 推進的,而新的特性也第一時間用在了 servo 的開發上,它們相互依存、相輔相成。可以說,rust 推出時,已經經受了一個巨大的、復雜的工程考驗,而 servo 推出出,也意味著 rust 真正可用。

這個意義在於用戶不是小白鼠,目前沒有其它新語言的東家是「如此有誠意」的。隨著三星的加入,大量三星員工已經提交許多代碼,未來的 rust 會在發布之前就經受過更多的商用大項目考驗,工程成熟度會非常高。

總結如下:

rust 定位非常明確,所以在 0.1 版本出來的時候,內存模型、並發模型、網路庫(使用libuv)、類型推斷、自舉、編譯(編譯到 llvm,而不是直接生成機器碼)。

這幾個現代工程語言最重要的東西都已經定了下來,而且選擇的都是最佳方案。相對地,另一個號稱並發的新語言做好這些都不知道是第幾個大版本了,而多核支持現在還是個笑話。

C. Rust 和 Go,哪個性能更好

要說性能,那是Rust更好。更多的編譯期優化、無 GC 等特點加持,開發高性能應用自然是 Rust 性能高。據統計利用 Rust 開發的 RipGrep 性能甚至賽過使用 C 開發的 Grep。

但是性能不是唯一考量,當你糾結 Borrow Check,糾結 unsafe,糾結 clone,糾結各種奇怪的類型限制的時候;當你 cargo build 怒草電腦風扇三分鍾的時候;人家 GoLang 可能早就發兩個版了。

同時 Rust 的語法花活眾多,遍歷數組可以寫循環也可以 for_each() 一行流。不像 GoLang 那麼白開水誰寫都差不多一個味道,經常第一天想到神來之筆快樂 Coding 到半夜第二天爬起來發現昨晚寫的都甚麼東西看不懂不如蜘蛛爬,這是墜痛苦的!

Go 的編譯器為了個編譯速度快連循環不變式提升、循環展開、對齊等等優化一個都不做,函數內斂一堆限制大多數情況都不做(比如函數里有個 for 或者 defer 或者 select 等,或者函數多於 40 個表達式),擁有的優化一隻手都能數的過來:

基礎優化欠缺,高級優化更是一個沒有,和在 Debug 配置編譯下的 -O0 優化的 C++ 差不多一個概念(而且跑得更慢),哪來的資本和 rust 比性能。

其他方面:

而且 Go 的 GC 吞吐量也很低,大多數情況下各方面 Go 跑的甚至都比 Java 更慢。只不過得益於 AOT 編譯的設計,相比 Java 而言除了內存佔用小和啟動速度快之外就沒有任何優勢了,比較適合拿來做性能不關鍵的命令行工具。

個人還是更喜歡 Rust。



D. 對比 Go 語言,Rust 有什麼優勢和劣勢

我並沒有什麼編程的經驗,覺得編程實在是太復雜了,不喜歡去研究太多,對這個也不怎麼懂,只能說自己是個半吊子,就是所掌握的知識,也是東拼西湊的,朋友和我說點兒,自己去書上看一點兒,只能說根據自己的體驗給出一些體會吧。


其實我覺得什麼代碼啊編程啊這些東西還是比較適合理工的學生去研究,我一看腦袋就大,完全不明白在講什麼。我大概了解的就是這些,語言的話大家可以多方面的去了解,也不是說有缺點就是不好,看配置看個人吧,每個人習慣不一樣,也許有的人用不穩定的還覺得挺好呢,有的人就喜歡比較完美的,在我看來編程這個東西真的是很復雜,會有很多的代碼,這些代碼弄得我自己頭都大了,有的時候還得去惡補一下。

E. 對比Go 語言,Rust 有什麼優勢和劣勢

Python 是腳本語言,也就是中間件語言,其內核仍然是純 c 的性能表達的,而主要性能消耗在腳本的實時編譯上。而對比c,同樣的功能,python可以表達比c更加精煉,當然犧牲了一些性能。如果確實對某個模組性能不滿意,還可以使用 c 編寫 Python 模塊為其加速。面對一些並不需要過多性能而可以獲得更快捷的開發速度,Python的優勢完全可以蓋過「劣勢」。可以說,Python基本完美。例如知乎就是使用 Python 製作的。Google 的許多頁面也是使用 Python 進行渲染的。

F. go和rust打包軟體大小

0.86MB。go和rust打包軟體大小是0.86MB,go和rust的軟體包是屬於整套的軟體包,需要將go和rust軟體包在windows的原文件里進行協同式解壓,只有經過協同式解壓之後才能進行安裝使用。

G. Java和Rust在實現多線程編程時的異同

Java的實現
打開Follower.java里的這個函數

這里的Follower.this.invitations就是我們的消息隊列,定義是:private LinkedList<Invitation> invitations;LinkedList不是線性安全的集合,需要我們加同步。具體的同步方法就是函數里寫的,通過Java常見的用wait,notify和notifyall給對象加鎖。
處理並發有wait、notify和notiyall,有興趣的朋友可以去這里了解一下:http://www.importnew.com/16453.html。Follower就是一個等待leader發送invitation,處理並返回結果的過程。
Leader.java
這么一段代碼:

裡面就是Leader發送邀請inv,並等待follower返回結果的大概邏輯,通過對消息體加鎖,是Java傳統的實現多線程並發的方式。還有消費者的消息隊列也會加鎖,在Java里,有個對象叫LinkedBlockingQueue,是不用加鎖就可以put和take的,但在例子里,我們選用了更簡單的LinkedList,也是為了表現一下加鎖的邏輯。
Rust的實現
Leader的結構為:

Follower的結構為:

對於其他語言轉過來的同學,這里的Vec,i32,bool都很好理解,不過裡面出現的Arc和Mutex,Sender,Receiver就是新東西了,上面這4個都是Rust標准庫的東西,也是這次分享要介紹的重點對象,是這4個東西共同實現了消息的生產,傳遞和消費。
下面簡單介紹一下分別是做什麼用的:
Arc<T>實現了sync介面。Sync介面是做什麼呢?權威資料是這么說的:當一個類型T實現了Sync,它向編譯器表明這個類型在多線程並發時沒有導致內存不安全的可能性。
如果看不懂不要緊,我們先看看實際中是怎麼用的:

在這個例子里,我們關注這幾句:
let data = Arc::new(Mutex::new(vec![1u32, 2, 3]));
let data = data.clone();
let mut data = data.lock().unwrap();
下面分別解釋一下是做什麼的:
簡單的說Arc::new表明了這是通過clone()方法來使用的,每clone,都會給該對象原子計數+1,通過引用計數的方法來保證對象只要還被其中任何一個線程引用就不會被釋放掉,從而保證了前面說的:這個類型在多線程並發時沒有導致內存不安全的可能性。
如果我們不定義為Arc<>就傳到其他線程使用,編譯器會報:
error: capture of moved value: `data`
data[i] += 1;
我們可以記住clone()就是Arc的用法。
接下來我們看Mutex:
Mutex實現了send介面。同樣,在權威資料里是這么描述的:這個類型的所有權可以在線程間安全的轉移
那我們又是怎麼用Mutex的呢?就是用lock().unwrap()。lock()的作用是獲取對象,如果當前有其他線程正在使用Mutex<T>裡面的T對象時,本線程就會阻塞,從而保證同時只有一個線程來訪問對象,mutex也另外提供了try_lock()的方法,是不阻塞的,只要其他線程被佔用,就返回err,通常Arc和Mutex都是一起使用的。
回到我最原始的題目,Mutex和Arc實現了對象本身的線程共享,但是在線程間如何傳遞這個對象呢?就是靠channel,channel通常是這么定義的let (tx, rx) = mpsc::channel();它會返回兩個對象tx和rx,就是之前我提到的sender和receiver。
在我的Rust實現里,關鍵的語句是以下幾個:
let leaders = (0..leader_cnt).map(|i|
Arc::new(Mutex::new(Leader::new(i,dance_types.len() as i32)))
).collect::<Vec<_>>();
這一句是new一堆leader出來,Arc和Mutex表明leader是可以多線程共享和訪問的。
同樣Follower也是:
let followers = (0..follower_cnt).map(|i|
Arc::new(Mutex::new(Follower::new(i,dance_types.len() as i32,leader_cnt)))
).collect::<Vec<_>>();
接下來這幾句就有點不好理解了。

這里定義了一堆的sender和receiver,其中把他們都作為leader和follower的成員變數存起來。大概意思就是每一個leader都通過sender列表可以發送invitation給所有follower,同時又有單個receiver來接受所有follower發給自己的處理結果inviresult。
同樣follower也是這么做。這樣在之後每一個follower和leader作為一個線程跑起來之後,都能在相互之間建立了一條通信的通道。
這個是和Java實現多線程並發最大的不同之處!Java是通過給對象加鎖,Rust是通過channel轉移對象的所有權,在代碼里,leader發送inv給folloer是下面這一句
match self.senders[*follower_id as usize].lock().unwrap().send(inv){,其中的lock().unwrap()是獲得該leader對該follower的發送通道的所有權,send(inv)就是轉移具體的發送對象invitation所有權了。
這個轉移按照我的理解,應該是內存拷貝。就是在follower接收的時候,let inv = match self.receiver.recv() { ,原來leader裡面的inv在send之後已經是不可訪問了,如果你之後再次訪問了inv,會報use of moved value錯誤,而follower裡面的inv則是在follower的棧里新生成的對象,所以,在Java裡面我只定義了invitation對象,但是在Rust裡面,我要再定義一個InviResult,因為我即使在follower線程裡面填了result欄位,leader線程也不能繼續訪問inv了。所以需要依靠follower再次發送一個invresult給leader,所以整個Rust程序大概就是這么一個思路。
實踐總結
之前我測試比較Java和Rust實現的性能時,由於沒有把調試信息去掉,導致Java比Rust慢很多,特別是那些調試信息都是調用String.format,這是比幾個string相加慢上10倍的方法,兩者都去掉調試信息後,leader和follower都會2000的時候,在我低端外星人筆記本里,性能差別大概是2倍吧,沒我想像中大,Rust的程序整個寫下來比較費力,一方面是對ownership機制不熟,思維沒有轉變過來,另一方面Rust的確需要開發者分部分精力到語法細節上。
編者註:馮總也有一些其它的實踐體會,請參見CSDN對馮耀明的專訪,請戳這里。也可以查看他的個人博客里的總結。
下面摘錄采訪中關於Rust的內容過來:
首先Rust裡面的ownership和lifetime概念真的很酷,就因為這個概念實現無內存泄露,野指針和安全並發。
其次,Rust的語法不簡單,也是有不少坑的,據說Rust的潛在用戶應該是現在的C和C++程序員,他們可能會覺得比較習慣,說不定還 覺得更簡單。由於ownership機制,一些在其他語言能夠跑通的程序在Rust下就要調整實現了,它會改變你寫程序的思維方式。據說一些寫Rust超 過半年的程序員已經愛上它了!
我對Rust感受較深的是下面幾點:
初學者不熟悉ownership機制,會無數次編譯失敗。但一旦編譯成功,那麼程序只剩下邏輯錯誤了。同樣,由於ownership機制,將來在項目里修改Rust代碼將可能是痛苦的過程,因為原來編譯通過的代碼可能加入新功能就編譯不過了,這是我的猜測。
Rust編譯速度慢,不過據說最近每一個Rust新發布的版本編譯速度都比之前的版本提高了30%。
Rust沒有類,有的是結構體加方法,我喜歡這種簡單的概念。
Rust沒有類繼承,只有介面,雖然介面可以提供默認的實現。這樣一來,在大型項目里原來類繼承來重用代碼的效果是否就要用成員變數實例來完成呢?
Rust沒有null,取而代之的是None和Option<T>,也因此,結構體在初始化的時候必須初始化所有欄位。
Rust有我一直很想要的錯誤值返回機制,而不必通過拋異常或者需要每每定義包含結果和錯誤體實現。
Rust用send和sync兩個介面來處理多線程並發,其中Arc<T>和Mutex<T>分別實現了這兩個介面,簡單易用。
Rust目前沒有一個強大的IDE,支持斷點調試,變數監控等。
它跟現在動態語言是兩個截然不同的方向,它適合一些資深的程序員,我倒是覺得有必要有這么一本書,叫《從C++到Rust,你需要改善的20個編程 習慣》,能從實踐上告訴開發者Rust里我們應該遵從什麼樣的編程習慣。Rust未來是否像C那樣流行開來成為新一代的主流語言沒有人能夠知道,但它絕對 是值得你去了解和關注的語言。
進一步的思考:反轉鏈表 - Java和Rust的不同實現
Rust的list應該怎麼定義,譬如反轉列表又是怎麼做呢?
由於ownership的機制和不存在空指針的情況,很多在其他帶GC的語言能夠跑起來的程序在Rust下面就要換一種做法。最近試用Rust的基礎數據結構時,更加加強了我的看法。下面以最原始的鏈表list為例。
在Java中,考慮最基本的鏈表定義
class ListNode {
int val;
ListNode next;

ListNode(int x) {
val = x;
}

@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("[");
sb.append(val);
ListNode pNext = this.next;
while (pNext != null) {
sb.append(",");
sb.append(pNext.val);
pNext = pNext.next;
}
sb.append("]");
return String.format("%s", sb.toString());
}
}
如果我們要反轉鏈表,可以這么做:
public ListNode reverseList(ListNode head) {
if (head == null) {
return null;
}
ListNode pNext = head.next;
ListNode pPrevious = null;
while (head != null) {
pNext = head.next;
head.next = pPrevious;
pPrevious = head;
head = pNext;
}
return pPrevious;
}
那如果我們按照一般思維,在Rust里對應的實現就是這樣子的:
struct ListNode{
id :i32,
next :Option<Box<ListNode>>
}
反轉鏈表:
fn reverseList2(head :&mut Option<Box<ListNode>>) -> Option<Box<ListNode>> {
match *head{
None => None,
Some(head) => {
let mut head = Some(head);
let mut pNext = head.unwrap().next;
let mut pPrevious:Option<Box<ListNode>> = None;
while true {
match head {
None =>{break;}
_ =>{}
}
pNext = head.unwrap().next;
head.unwrap().next = pPrevious;
pPrevious = head;
head = pNext;
}
pPrevious
}
}
}
然後編譯,報了以下錯誤:
=》match *head{

ERROR:cannot move out of borrowed content
=》 pNext = head.unwrap().next;
ERROR:cuse of moved value: `head`

這些錯誤就是因為Rust的ownership機制,讓我們無法像Java或者C++里保存臨時變數,特別是在循環里。反復試過各種寫法,都行不通。
最後,換成這么來做
鏈表定義:
use List::*;

enum List {
Cons1(i32, Box<List>),
Nil,
}

// Methods can be attached to an enum
impl List {
#[inline]
fn new() -> List {
Nil
}

#[inline]
fn prepend(self, elem: i32) -> List {
Cons1(elem, Box::new(self))
}

fn len(&self) -> i32 {
match *self {
Cons1(_, ref tail) => 1 + tail.len(),
Nil => 0
}
}

fn stringify(&self) -> String {
match *self {
Cons1(head, ref tail) => {
format!("{}, {}", head, tail.stringify())
},
Nil => {
format!("Nil")
},
}
}
}

fn reverseList(list:List, acc:List ) -> List{
match list{
Cons1(val,tail) => {
reverseList(*tail,acc.prepend(val))
}
Nil => acc
}
}

fn main() {
let mut head = List::new();
let mut i=0;
while i < 10 {
i+=1;
head = head.prepend(i);
}
println!("{:30}",head.stringify());
let result = List::new();
let result = reverseList(head,result);
<span style="white-space:pre"> </span>println!("{:30}",result.stringify());
}
從結果可以看到,鏈表已經實現反轉了。所以在Rust下面,很多做法都要換一下。有人說這就是Rust函數式編程的思維。我但願這種遞歸式的做法不會有溢出。

H. rust是前端還是後端

後端。

Rust是一款高級通用語言,而且屬於少有的一款兼顧開發和執行效率的編程語言。Rust結合了腳本語言的語法結構和C語言編譯執行效率,並且具有類似垃圾回收和數據類型及所有權系統等功能,所以可靠性和高性能運行都屬於Rust的特色。

雖然是一個非常年輕的編程語言,但是Rust可以算是最近幾年最流行的編程語言。5月發布的Stack Overflow 2020開發者調查中,Rust被86.1%開發者選擇為「最喜歡」的編程語言,比第二名TypeScript高出近20%。

雖然Rust並不是一個專屬的網路應用開發語言,但是作為一個以安全著稱的編輯語言,實際上是非常適合網路開發的。而且因為是編譯型語言,編譯器也能在過程中就安全穩定的問題作出提醒,作為後端網路開發還是不錯的一個優勢。

Rust的通用庫中已經包含了類似TcpListener這樣的網路通訊庫,可以直接通過調用std : : net 下面的TcpListener來直接監聽Tcp埠,然後再處理Request。這點上與一些腳本型的編程語言比要自由得很多。

Rust作為比較流行的編程語言,也有不少第三方HTTP庫來支持Web開發,可以不用再花時間從底層開發,比較熱門的庫像Hyper或者Tide都是被不少Web開發框架用到的。Rust下Web開發框架也不少,比較熱門的有Rocket、Actix-Web、Tower-web、Warp等等框架。

I. 為什麼Rust這樣的語言還需要C/C++編譯器

需要用 VS 的鏈接器,應該是需要支持 FFI 的原因。Windows 是 Rust 承諾要支持的主要平台之一,這意味著,Rust要有能力和Windows上的靜態庫和動態庫來交互。這時候,MSVC的ABI就是繞不過去的一個問題。可以參考 Rustup 的官方文檔對Windows平台的描述,rust-lang-nursery/rustup.rs。 Windows平台上有兩套ABI,一個是MSVC,一個是MinGW。所以你其實有兩個選擇,要麼安裝 msvc,然後
rustup install stable-x86_64-pc-windows-msvc
要麼安裝 MinGW,然後
rustup install stable-x86_64-pc-windows-gnu
在 Rustup 的文檔上有這么一句話 By default rustup on Windows configures Rust to target the 32-bit MSVC ABI, that is the i686-pc-windows-msvc target triple. 所以,默認安裝的話,你需要安裝 msvc。

閱讀全文

與rust編譯後小嗎相關的資料

熱點內容
pdf轉dwg怎麼轉 瀏覽:51
單片機微小電阻測量 瀏覽:134
表格25兆怎麼壓縮 瀏覽:65
java開發公司的 瀏覽:127
東風天錦壓縮車工作指示燈不亮 瀏覽:983
劍俠情緣1源碼 瀏覽:530
cad2011怎麼轉換成pdf格式 瀏覽:964
傳祺gs5安卓車機如何還原車機 瀏覽:900
單片機和編程器互相傳輸數據 瀏覽:90
app訂單怎麼取消 瀏覽:467
程序員用雙顯示器有什麼作用 瀏覽:609
網約車演算法殺熟 瀏覽:6
卡薩帝用的什麼壓縮機 瀏覽:155
350乘20演算法 瀏覽:90
自助編程軟體app 瀏覽:438
伺服器如何看日活數 瀏覽:686
數控車床原理圖及編程 瀏覽:289
java文件流下載 瀏覽:340
編程工作工資多少 瀏覽:441
專業安全文件夾 瀏覽:781