開(kāi)源精選》是我們分享Github、Gitee等開(kāi)源社區(qū)中優(yōu)質(zhì)項(xiàng)目的欄目,包括技術(shù)、學(xué)習(xí)、實(shí)用與各種有趣的內(nèi)容。本期推薦的是一個(gè)功能強(qiáng)大的串口工具。支持Lua自動(dòng)化處理、串口調(diào)試、串口監(jiān)聽(tīng)、串口曲線、TCP測(cè)試、MQTT測(cè)試、編碼轉(zhuǎn)換、亂碼恢復(fù)等功能。
使用Lua腳本提前處理待發(fā)送的數(shù)據(jù)
return uartData.."\r\n"
return uartData:fromHex()
此腳本可將形如30313233發(fā)送數(shù)據(jù),處理為0123的結(jié)果
json = require("JSON")
t = uartData:split(",")
return json:encode({
key1 = t[1],
key2 = t[2],
key3 = t[3],
})
此腳本可將形如a,b,c發(fā)送數(shù)據(jù),處理為{"key1":"a","key2":"b","key3":"c"}的結(jié)果。
獨(dú)立的Lua腳本自動(dòng)處理串口收發(fā)
右側(cè)的Lua腳本調(diào)試區(qū)域,可直接運(yùn)行你寫(xiě)的串口測(cè)試腳本,如軟件自帶的:
--注冊(cè)串口接收函數(shù)
uartReceive = function (data)
log.info("uartReceive",data)
sys.publish("UART",data)--發(fā)布消息
end
--新建任務(wù),等待接收到消息再繼續(xù)運(yùn)行
sys.taskInit(function()
while true do
local _,udata = sys.waitUntil("UART")--等待消息
log.info("task waitUntil",udata)
local sendResult = apiSendUartData("ok!")--發(fā)送串口消息
log.info("uart send",sendResult)
end
end)
--新建任務(wù),每休眠1000ms繼續(xù)一次
sys.taskInit(function()
while true do
sys.wait(1000)--等待1000ms
log.info("task wait",os.time())
end
end)
--1000ms循環(huán)定時(shí)器
sys.timerLoopStart(log.info,1000,"timer test")
甚至你可以利用xlua框架的特性,調(diào)用C#接口完成任何你想做的事情
request = CS.System.Net.WebRequest.Create("http://example.com")
request.ContentType = "text/html;charset=UTF-8";
request.Timeout = 5000;--超時(shí)時(shí)間
request.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36 Vivaldi/2.2.1388.37";
response = request:GetResponse():GetResponseStream()
myStreamReader = CS.System.IO.StreamReader(response, CS.System.Text.Encoding.UTF8);
print(myStreamReader:ReadToEnd())--打印獲取的body內(nèi)容
myStreamReader:Close()
response:Close()
使用此功能,你可以完成大部分的自動(dòng)化串口調(diào)試操作。
-END-
開(kāi)源協(xié)議:Apache-2.0
開(kāi)源地址:https://gitee.com/chenxuuu/llcom
TML(HyperText Markup Language)是一種用于創(chuàng)建網(wǎng)頁(yè)的標(biāo)準(zhǔn)標(biāo)記語(yǔ)言。在HTML中,"元素"和"標(biāo)簽"是構(gòu)建網(wǎng)頁(yè)的基本組成部分,它們一起定義了網(wǎng)頁(yè)的結(jié)構(gòu)和內(nèi)容。HTML標(biāo)簽是用來(lái)定義HTML元素的開(kāi)始和結(jié)束的,而HTML元素是由標(biāo)簽及其包含的內(nèi)容組成的。
參考文檔:https://www.cjavapy.com/article/3303/
HTML元素指的是從開(kāi)始標(biāo)簽到結(jié)束標(biāo)簽的所有內(nèi)容。它們是HTML文檔的構(gòu)建塊,用于創(chuàng)建和組織網(wǎng)頁(yè)內(nèi)容。HTML元素可以包含文本、圖片、鏈接、表格等多種類(lèi)型的數(shù)據(jù)。元素可能包括一個(gè)開(kāi)始標(biāo)簽和一個(gè)結(jié)束標(biāo)簽,也可能只有一個(gè)標(biāo)簽(在自閉合元素的情況下)。
1) <!DOCTYPE> 聲明
用于定義文檔類(lèi)型,告訴瀏覽器此文檔使用哪個(gè)HTML版本。
<!DOCTYPE html>
2) <html>
根元素,包含整個(gè)HTML文檔。
<html lang="en">
</html>
3) <head>
包含文檔的元數(shù)據(jù),如標(biāo)題、字符集聲明和鏈接到樣式表。
<head>
<title>頁(yè)面標(biāo)題</title>
<meta charset="UTF-8">
</head>
4)<title>
定義文檔的標(biāo)題,顯示在瀏覽器的標(biāo)題欄或頁(yè)面的標(biāo)簽頁(yè)上。
<title>這是文檔的標(biāo)題</title>
5)<body>
包含文檔的所有可見(jiàn)內(nèi)容,如文本、圖片、鏈接和其他多媒體元素。
<body>
<h1>這是一個(gè)主標(biāo)題</h1>
<p>這是一個(gè)段落。</p>
</body>
6) <header>
定義一個(gè)區(qū)域或頁(yè)面的頭部,通常包含標(biāo)題和導(dǎo)航鏈接。
<header>
<h1>網(wǎng)站標(biāo)題</h1>
<nav>
<ul>
<li><a href="#">首頁(yè)</a></li>
<li><a href="#">關(guān)于</a></li>
</ul>
</nav>
</header>
7) <footer>
定義頁(yè)面或區(qū)域的頁(yè)腳部分,通常包含版權(quán)信息、聯(lián)系信息等。
<footer>
<p>版權(quán)所有 ? 2024</p>
</footer>
8) <nav>
定義導(dǎo)航鏈接的部分,用于頁(yè)面內(nèi)或頁(yè)面間的導(dǎo)航。
<nav>
<ul>
<li><a href="#">首頁(yè)</a></li>
<li><a href="#">新聞</a></li>
</ul>
</nav>
9)<section>
定義文檔中的一個(gè)獨(dú)立部分,通常與標(biāo)題一起使用。
<section>
<h2>章節(jié)標(biāo)題</h2>
<p>這是該章節(jié)的一些內(nèi)容。</p>
</section>
10. <article>
定義可以獨(dú)立于內(nèi)容其余部分的完整自包含內(nèi)容,例如博客帖子或新聞文章。
<article>
<h2>文章標(biāo)題</h2>
<p>文章內(nèi)容...</p>
</article>
11. <aside>
定義與周?chē)鷥?nèi)容稍微分離的內(nèi)容,如側(cè)邊欄或廣告欄。
<aside>
<p>這是一些附加信息。</p>
</aside>
12. <figure> 和 <figcaption>
<figure> 定義獨(dú)立的流內(nèi)容(如圖表、圖像、代碼示例等),<figcaption> 提供該內(nèi)容的標(biāo)題。
<figure>
<img src="image.jpg" alt="描述性文本">
<figcaption>圖像標(biāo)題</figcaption>
</figure>
HTML標(biāo)簽是HTML元素的一部分,用于從邏輯上開(kāi)始或結(jié)束一個(gè)元素。標(biāo)簽通常成對(duì)出現(xiàn),包括一個(gè)開(kāi)始標(biāo)簽和一個(gè)對(duì)應(yīng)的結(jié)束標(biāo)簽,結(jié)束標(biāo)簽的名稱前會(huì)有一個(gè)斜線(/)作為區(qū)分。有些HTML標(biāo)簽是自閉合的,意味著它們不需要結(jié)束標(biāo)簽,如圖像標(biāo)簽(<img />)和換行標(biāo)簽(<br />)。
標(biāo)簽 | 說(shuō)明 |
<!DOCTYPE> | 聲明文檔類(lèi)型和HTML版本。 |
<html> | 標(biāo)識(shí)一個(gè)HTML文檔的根元素。 |
<head> | 包含了文檔的元數(shù)據(jù)。 |
<title> | 指定文檔的標(biāo)題。 |
<body> | 包含了可見(jiàn)的頁(yè)面內(nèi)容。 |
<h1> - <h6> | 定義標(biāo)題,從 <h1> 到 <h6> 重要性遞減。 |
<p> | 定義段落。 |
<br> | 插入一個(gè)換行符。 |
<hr> | 在頁(yè)面上繪制一條水平線。 |
<b> | 定義粗體文本。 |
<i> | 定義斜體文本。 |
<u> | 定義下劃線文本。 |
<strong> | 定義重要文本。 |
<em> | 定義強(qiáng)調(diào)文本。 |
<mark> | 定義被標(biāo)記或高亮的文本。 |
<small> | 定義小號(hào)文本。 |
<sub> | 定義下標(biāo)文本。 |
<sup> | 定義上標(biāo)文本。 |
<a> | 定義超鏈接。 |
<img> | 在頁(yè)面中嵌入圖像。 |
<ul> | 定義無(wú)序列表。 |
<ol> | 定義有序列表。 |
<li> | 定義列表項(xiàng)。 |
<table> | 定義表格。 |
<th> | 定義表格的表頭單元格。 |
<tr> | 定義表格的行。 |
<td> | 定義表格單元。 |
<form> | 定義HTML表單。 |
<input> | 定義輸入控件。 |
<textarea> | 定義多行文本輸入控件。 |
<button> | 定義按鈕。 |
<select> | 定義下拉列表。 |
<option> | 定義下拉列表中的選項(xiàng)。 |
<article> | 定義文章。 |
<section> | 定義文檔中的一個(gè)區(qū)域(或節(jié))。 |
<header> | 定義介紹性內(nèi)容或?qū)Ш芥溄拥娜萜鳌?/p> |
<footer> | 定義注腳或文檔的頁(yè)腳。 |
<nav> | 定義導(dǎo)航鏈接的部分。 |
<aside> | 定義側(cè)邊欄內(nèi)容。 |
使用示例:
<!DOCTYPE html>
使用示例:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>HTML標(biāo)簽使用示例</title>
</head>
<body>
<header>
<h1>歡迎來(lái)到我的網(wǎng)頁(yè)</h1>
<nav>
<a href="#content">主要內(nèi)容</a> |
<a href="#contact-form">聯(lián)系表單</a>
</nav>
</header>
<section id="content">
<article>
<h2>HTML基礎(chǔ)</h2>
<p>HTML是構(gòu)建網(wǎng)頁(yè)的基石。<strong>標(biāo)簽</strong>是它的核心組成部分。<mark>本文</mark>介紹了一些最常用的HTML標(biāo)簽。</p>
</article>
<aside>
<h3>注意</h3>
<p>記得檢查HTML5的新特性和標(biāo)簽。</p>
</aside>
<ul>
<li>文本標(biāo)簽</li>
<li>列表</li>
<li>表格</li>
<li>表單</li>
</ul>
<ol>
<li>先介紹基礎(chǔ)</li>
<li>然后是進(jìn)階</li>
</ol>
<table>
<tr>
<th>標(biāo)簽</th>
<th>描述</th>
</tr>
<tr>
<td><p></td>
<td>段落標(biāo)簽</td>
</tr>
<tr>
<td><a></td>
<td>鏈接標(biāo)簽</td>
</tr>
</table>
</section>
<section id="images">
<h2>圖片</h2>
<img src="example.jpg" alt="示例圖片">
</section>
<footer>
<section id="contact-form">
<h2>聯(lián)系我們</h2>
<form>
<label for="name">姓名:</label>
<input type="text" id="name" name="name"><br>
<label for="email">電子郵件:</label>
<input type="email" id="email" name="email"><br>
<input type="submit" value="提交">
</form>
</section>
<p>? 2024 HTML標(biāo)簽示例</p>
</footer>
</body>
</html>
參考文檔:Hhttps://www.cjavapy.com/article/3303/
者:李彥鋒,騰訊 IEG 運(yùn)營(yíng)開(kāi)發(fā)工程師
一直想寫(xiě)一篇關(guān)于C語(yǔ)言的文章,里面包含C語(yǔ)言的發(fā)展史、創(chuàng)始人等相關(guān)事跡。但是卻遲遲未寫(xiě),主要原因是因?yàn)椋涸谖铱磥?lái),這個(gè)語(yǔ)言太過(guò)于偉大、耀眼。作為一個(gè)僅僅使用過(guò)C語(yǔ)言的普通開(kāi)發(fā)來(lái)說(shuō),完全沒(méi)資格去寫(xiě)。但是,最近在看過(guò)一篇丹尼斯.里奇寫(xiě)的《C語(yǔ)言發(fā)展史》之后,堅(jiān)定了我寫(xiě)這篇文章的決心。不是歌功頌德,僅僅是以一種客觀的視角去欣賞。
任何一種新事物的出現(xiàn)都不是來(lái)自于偶然,而是時(shí)代所驅(qū)使的必然結(jié)果。
如果你問(wèn)我:C語(yǔ)言有多偉大。那么,我可能會(huì)想一下,說(shuō):多偉大我不知道,但是我知道很偉大。
這里,我想說(shuō)一句可能有點(diǎn)片面的話,就是:如今這世界上,凡是帶電的地方,可能都會(huì)有她(C語(yǔ)言)或者她的子孫的影子。
任何比C語(yǔ)言更低級(jí)的語(yǔ)言,都不足以完整地抽象一個(gè)計(jì)算機(jī)系統(tǒng);任何比C高級(jí)的語(yǔ)言,都可以用C來(lái)實(shí)現(xiàn)。
Ritchie 貝爾實(shí)驗(yàn)室的個(gè)人主頁(yè)地址 https://www.bell-labs.com/usr/dmr/www/index.html
丹尼斯·麥卡利斯泰爾·里奇(英語(yǔ):Dennis MacAlistair Ritchie,1941年9月9日-2011年10月12日),美國(guó)計(jì)算機(jī)科學(xué)家。黑客圈子通常稱他為“dmr”。他是C語(yǔ)言的創(chuàng)造者、Unix操作系統(tǒng)的關(guān)鍵開(kāi)發(fā)者,對(duì)計(jì)算機(jī)領(lǐng)域產(chǎn)生了深遠(yuǎn)影響,并與肯·湯普遜同為1983年圖靈獎(jiǎng)得主。
丹尼斯.里奇 生平時(shí)間線
麻省理工大學(xué)計(jì)算機(jī)系的馬丁教授評(píng)價(jià)說(shuō):"如果說(shuō),喬布斯是可視化產(chǎn)品中的國(guó)王,那么里奇就是不可見(jiàn)王國(guó)中的君主。喬布斯的貢獻(xiàn)在于,他如此了解用戶的需求和渴求,以至于創(chuàng)造出了讓當(dāng)代人樂(lè)不思蜀的科技產(chǎn)品。然而,卻是里奇先生為這些產(chǎn)品提供了最核心的部件,人們看不到這些部件,卻每天都在使用著。"
克尼漢評(píng)價(jià)道:牛頓說(shuō)他是站在巨人的肩膀上,如今,我們都站在里奇的肩膀上。
為了簡(jiǎn)潔起見(jiàn),我(Dennis M.Ritchie)省略了對(duì)C本身,其父級(jí)B [Johnson 73]和其祖父母BCPL [Richards 79]的完整描述,而只關(guān)注每種語(yǔ)言的特征元素以及它們?nèi)绾窝葑儭?/span>
This paper is about the development of the C programming language, the influences on it, and the conditions under which it was created. For the sake of brevity, I omit full descriptions of C itself, its parent B [Johnson 73] and its grandparent BCPL [Richards 79], and instead concentrate on characteristic elements of each language and how they evolved.
https://www.bell-labs.com/usr/dmr/www/chist.html
這段文字出自C語(yǔ)言之父丹尼斯.M.里奇所寫(xiě)的一篇關(guān)于《C語(yǔ)言發(fā)展史》的文章,文中明確指出C語(yǔ)言源自于B、BCPL兩種語(yǔ)言。可以把C語(yǔ)言看做是站在巨人的肩上,順應(yīng)時(shí)代潮流的后浪。
Martin Richards
Martin Richards's BCPL Reference Manual, 1967 https://web.archive.org/web/20080622171914/http://cm.bell-labs.com/cm/cs/who/dmr/bcpl.html
馬丁·理查德(英語(yǔ):Martin Richards,1940年7月21日-),生于英國(guó),計(jì)算機(jī)科學(xué)家,為BCPL編程語(yǔ)言的發(fā)明者,發(fā)展了TRIPOS操作系統(tǒng)。
1966年,馬丁·理查德在劍橋大學(xué),以CPL編程語(yǔ)言為基礎(chǔ),發(fā)明了BCPL編程語(yǔ)言。
Kenneth Lane Thompson
肯尼斯·蘭·湯普遜(英語(yǔ):Kenneth Lane Thompson,1943年2月4日-)小名肯·湯普遜(英語(yǔ):Ken Thompson),美國(guó)計(jì)算機(jī)科學(xué)學(xué)者和工程師。黑客文化圈子通常稱他為“ken”。在貝爾實(shí)驗(yàn)室工作期間,湯普遜設(shè)計(jì)和實(shí)現(xiàn)了Unix操作系統(tǒng)。他創(chuàng)造了B語(yǔ)言(基于BCPL) — C語(yǔ)言的前身,而且他是Plan 9操作系統(tǒng)的創(chuàng)造者和開(kāi)發(fā)者之一。與丹尼斯·里奇同為1983年圖靈獎(jiǎng)得主。
2006年,湯普遜進(jìn)入Google公司工作,與他人共同設(shè)計(jì)了Go語(yǔ)言。
日益精進(jìn)
站在巨人的肩上
坐著的是Ken 站著的是Dennis
與優(yōu)秀之人為伍
不畏得失,做有趣的事
左Ken 右Dennis | 右上角:Unix標(biāo)識(shí)牌
言傳身教
感謝丹尼斯.里奇留給了這世界一本“C語(yǔ)言圣經(jīng)”
可惜的是,當(dāng)年筆者大學(xué)學(xué)的是譚浩強(qiáng)譚老師的C語(yǔ)言
Dennis與《The C Programming Language》
互相成就
終成正果
你做了什么,最終會(huì)被世人看到
1999年獲得美國(guó)國(guó)家技術(shù)獎(jiǎng) [左一:Ken | 左二:Dennis | 右一:克林頓]
從這些老照片中,我隱隱約約看到了幾行小字,寫(xiě)著:
1.與優(yōu)秀之人為伍
2.互相成就
試想,有多么重要?
Computer Languages History https://www.levenez.com/lang/
從圖中時(shí)間線,可以明顯的看出C語(yǔ)言的起源以及時(shí)間節(jié)點(diǎn)。
有時(shí)候不得不說(shuō)時(shí)勢(shì)造英雄,在1969~1971年之間著名的操作系統(tǒng)Unix從肯.湯普遜手中誕生,作為一種大型的系統(tǒng)性軟件來(lái)說(shuō),極其需要一種可靠的高級(jí)語(yǔ)言的出現(xiàn)(當(dāng)時(shí)的低級(jí)語(yǔ)言指的是匯編,因?yàn)橹暗牟僮飨到y(tǒng)是用匯編寫(xiě)的)。這個(gè)時(shí)候的丹尼斯.里奇也沒(méi)閑著,在對(duì)B語(yǔ)言改良之后,就誕生了帶有類(lèi)型的C語(yǔ)言(據(jù)里奇自己說(shuō),有一段時(shí)間稱這種改良的語(yǔ)言為NB。即:new B。不過(guò),在我們這些吃瓜群眾眼中看來(lái)也確實(shí)NB)。
In 1971 I began to extend the B language by adding a character type and also rewrote its compiler to generate PDP-11 machine instructions instead of threaded code. Thus the transition from B to C was contemporaneous with the creation of a compiler capable of producing programs fast and small enough to compete with assembly language. I called the slightly-extended language NB, for `new B.'
Unix的誕生與C語(yǔ)言被廣泛的傳播、使用,有著密切的聯(lián)系。
上圖時(shí)間線只顯示前幾個(gè)與C語(yǔ)言在相同時(shí)間段內(nèi)誕生的Unix版本(當(dāng)然,感興趣的話,可以查詢Unix相關(guān)發(fā)展史,絕對(duì)會(huì)讓你大吃一驚。其中最著名的幾個(gè)分支:BSD、minix、Linux...)。
下面,通過(guò)在網(wǎng)上找得到的部分Unix內(nèi)核源碼,來(lái)追溯一下C語(yǔ)言出現(xiàn)的時(shí)機(jī)。
PDP-Unix系統(tǒng)內(nèi)核代碼文件
PDP-7 Unix https://minnie.tuhs.org/cgi-bin/utree.pl?file=PDP7-Unix
可以看到基本都是用匯編寫(xiě)的(文件名后綴.s)。為什么用基本這個(gè)詞呢?因?yàn)椋谙到y(tǒng)里面有一部分命令是用B語(yǔ)言寫(xiě)的。
First Edition Unix系統(tǒng)內(nèi)核代碼文件
https://minnie.tuhs.org/cgi-bin/utree.pl?file=V1
可以看到,還是用匯編寫(xiě)的(文件名后綴.s)。
Second Edition Unix系統(tǒng)內(nèi)核代碼文件
Second Edition Unix The second edition of Unix was developed for the PDP-11 at Bell Labs by Ken Thompson, Dennis Ritchie and others. It extended the First Edition with more system calls and more commands. This edition also saw the beginning of the C language, which was used to write some of the commands.
https://minnie.tuhs.org/cgi-bin/utree.pl?file=V2
到這個(gè)版本,已經(jīng)可以看到C語(yǔ)言的身影了。
從C語(yǔ)言在Unix V2版本出現(xiàn)之后,Unix的V3版本開(kāi)始,已經(jīng)可以在Unix內(nèi)核中見(jiàn)到大量C語(yǔ)言編寫(xiě)的代碼。
據(jù)里奇所說(shuō):到1973年初,現(xiàn)代C的基本知識(shí)已經(jīng)完成。C語(yǔ)言和編譯器強(qiáng)大到,足以讓我們?cè)诋?dāng)年夏天用C重寫(xiě)PDP-11的Unix內(nèi)核 (也就是Unix的V3版本)。
By early 1973, the essentials of modern C were complete. The language and compiler were strong enough to permit us to rewrite the Unix kernel for the PDP-11 in C during the summer of that year.
到了這個(gè)時(shí)間節(jié)點(diǎn),基本可以肯定的是C語(yǔ)言、Unix的大部分核心都已經(jīng)完善。剩下要做的就是,可移植性、標(biāo)準(zhǔn)化。
后面的故事,大家可能也聽(tīng)說(shuō)過(guò):后來(lái)學(xué)術(shù)和政府組織中都在使用Unix,也正是由于Unix的風(fēng)靡與興盛,帶動(dòng)了C語(yǔ)言被廣泛的傳播、使用。
在1980年代,C語(yǔ)言的使用廣泛傳播,并且?guī)缀跛袡C(jī)器體系結(jié)構(gòu)和操作系統(tǒng)都可以使用編譯器。尤其是,它已成為個(gè)人計(jì)算機(jī)的編程工具,無(wú)論是用于這些機(jī)器的商業(yè)軟件制造商,還是對(duì)編程感興趣的最終用戶,都非常受歡迎。
During the 1980s the use of the C language spread widely, and compilers became available on nearly every machine architecture and operating system; in particular it became popular as a programming tool for personal computers, both for manufacturers of commercial software for these machines, and for end-users interested in programming.
這也就是所謂的互相成就。
一句話概括就是:不畏得失、日漸精進(jìn),最終互相成就。
不知道你有沒(méi)有想過(guò),大家都用C語(yǔ)言或基于C語(yǔ)言的語(yǔ)言來(lái)寫(xiě)編譯器,那么世界上第一個(gè)C語(yǔ)言編譯器又是怎么編寫(xiě)的呢?這不是一個(gè)“雞和蛋”的問(wèn)題……
回顧一下C語(yǔ)言歷史:Tomphson在BCPL的基礎(chǔ)上開(kāi)發(fā)了B語(yǔ)言,Ritchie又在B語(yǔ)言的基礎(chǔ)上成功開(kāi)發(fā)出了現(xiàn)在的C語(yǔ)言。在C語(yǔ)言被用作系統(tǒng)編程語(yǔ)言之前,Tomphson也用過(guò)B語(yǔ)言編寫(xiě)過(guò)操作系統(tǒng)。可見(jiàn)在C語(yǔ)言實(shí)現(xiàn)以前,B語(yǔ)言已經(jīng)可以投入使用了。因此第一個(gè)C語(yǔ)言編譯器的原型完全可能是用B語(yǔ)言或者混合B語(yǔ)言與PDP匯編語(yǔ)言編寫(xiě)的。
我們現(xiàn)在都知道,B語(yǔ)言的執(zhí)行效率比較低,但是如果全部用匯編語(yǔ)言來(lái)編寫(xiě),不僅開(kāi)發(fā)周期長(zhǎng)、維護(hù)難度大,更可怕的是失去了高級(jí)程序設(shè)計(jì)語(yǔ)言必需的移植性。
所以早期的C語(yǔ)言編譯器就采取了一個(gè)取巧的辦法:先用匯編語(yǔ)言編寫(xiě)一個(gè)C語(yǔ)言的一個(gè)子集的編譯器,再通過(guò)這個(gè)子集去遞推,進(jìn)而完成完整的C語(yǔ)言編譯器。
詳細(xì)的過(guò)程如下:先創(chuàng)造一個(gè)只有C語(yǔ)言最基本功能的子集,記作C0語(yǔ)言,C0語(yǔ)言已經(jīng)足夠簡(jiǎn)單了,可以直接用匯編語(yǔ)言編寫(xiě)出C0的編譯器。依靠C0已有的功能,設(shè)計(jì)比C0復(fù)雜,但仍然不完整的C語(yǔ)言的又一個(gè)子集C1語(yǔ)言,其中C0屬于C1,C1屬于C,用C0開(kāi)發(fā)出C1語(yǔ)言的編譯器。在C1的基礎(chǔ)上設(shè)計(jì)C語(yǔ)言的又一個(gè)子集C2語(yǔ)言,C2語(yǔ)言比C1復(fù)雜,但是仍然不是完整的C語(yǔ)言,開(kāi)發(fā)出C2語(yǔ)言的編譯器 …… 如此直到CN,CN已經(jīng)足夠強(qiáng)大了,這時(shí)候就足夠開(kāi)發(fā)出完整的C語(yǔ)言編譯器的實(shí)現(xiàn)了。至于這里的N是多少,這取決于你的目標(biāo)語(yǔ)言(這里是C語(yǔ)言)的復(fù)雜程度和程序員的編程能力。簡(jiǎn)單地說(shuō),如果到了某個(gè)子集階段,可以很方便地利用現(xiàn)有功能實(shí)現(xiàn)C語(yǔ)言時(shí),那么你就找到N了。下面的圖說(shuō)明了這個(gè)抽象過(guò)程:
https://kknews.cc/tech/bx2r3j.html 介紹一個(gè)概念,“自編譯”Self-Compile,也就是對(duì)于某些具有明顯自舉性質(zhì)的強(qiáng)類(lèi)型(所謂強(qiáng)類(lèi)型就是程序中的每個(gè)變量必須聲明類(lèi)型后才能使用,比如C語(yǔ)言,相反有些腳本語(yǔ)言則根本沒(méi)有類(lèi)型這一說(shuō)法)編程語(yǔ)言,可以借助它們的一個(gè)有限小子集,通過(guò)有限次數(shù)的遞推來(lái)實(shí)現(xiàn)對(duì)它們自身的表述,這樣的語(yǔ)言有C、Pascal、Ada等等,至于為什么可以自編譯,可以參見(jiàn)清華大學(xué)出版社的《編譯原理》,書(shū)中實(shí)現(xiàn)了一個(gè)Pascal的子集的編譯器。
https://zhuanlan.zhihu.com/p/136102461
而這個(gè)過(guò)程也在Unix V2版本中找到了證據(jù)。
肯恩·湯普森,丹尼斯·里奇和其他人在貝爾實(shí)驗(yàn)室為PDP-11開(kāi)發(fā)了Unix的第二版。它通過(guò)更多的系統(tǒng)調(diào)用和更多的命令擴(kuò)展了第一版。此版本還看到了C語(yǔ)言的開(kāi)始,該語(yǔ)言用于編寫(xiě)一些命令。
此處的代碼僅是某些命令,某些庫(kù)函數(shù)和C編譯器的源代碼。c /中的文件來(lái)自 last1120c.tar.gz 磁帶,并構(gòu)成了第二版Unix的有效C編譯器。
下載地址:http://minnie.tuhs.org/Archive/Applications/Early_C_Compilers/last1120c.tar.gz
The second edition of Unix was developed for the PDP-11 at Bell Labs by Ken Thompson, Dennis Ritchie and others. It extended the First Edition with more system calls and more commands. This edition also saw the beginning of the C language, which was used to write some of the commands.
The code here is only the source to some of the commands, some of the library functions, and the C compiler. The files in c/ come from the last1120c.tar.gz tape, and form a working C compiler for Second Edition Unix.
https://minnie.tuhs.org/cgi-bin/utree.pl?file=V2
下載源碼解壓縮之后,目錄結(jié)構(gòu)如下:
感興趣的小伙伴可以下載下來(lái)研究一下。
如果想要找到一種好的方式,來(lái)進(jìn)行編程語(yǔ)言之間比較的話,那么非代碼莫屬。
下面分別使用BCPL、B、C三種語(yǔ)言實(shí)現(xiàn)一個(gè)簡(jiǎn)單的程序:程序?qū)⑷齻€(gè)數(shù)字a、b、c相加,并將結(jié)果賦值給sum,最后打印總和。
BCPL https://zh.wikipedia.org/wiki/BCPL
GET "libhdr"
LET start() = VALOF
{ LET a, b, c = 1, 2, ,3
sum := a + b + c
writen(sum)
}
從BCPL到B的過(guò)渡中,決定使用單個(gè)字符 = 代替賦值 :=
Other fiddles in the transition from BCPL to B were introduced as a matter of taste, and some remain controversial, for example the decision to use the single character = for assignment instead of :=. Similarly, B uses /**/ to enclose comments, where BCPL uses //, to ignore text up to the end of the line. The legacy of PL/I is evident here. (C++ has resurrected the BCPL comment convention.) Fortran influenced the syntax of declarations: B declarations begin with a specifier like auto or static, followed by a list of names, and C not only followed this style but ornamented it by placing its type keywords at the start of declarations.
https://www.bell-labs.com/usr/dmr/www/chist.html
A TUTORIAL INTRODUCTION TO THE LANGUAGE B https://web.archive.org/web/20070807110157/http://cm.bell-labs.com/cm/cs/who/dmr/btut.html
B語(yǔ)言的語(yǔ)言結(jié)構(gòu)
main() {
-- statements --
}
newfunc(arg1, arg2) {
-- statements --
}
fun3(arg) {
-- more statements --
}
B語(yǔ)言代碼示例
main() {
auto a, b, c, sum;
a = 1; b = 2; c = 3;
sum = a+b+c;
putnumb(sum);
}
#include <stdio.h>
void main(){
int a,b,c,sum;
a=1; b=2; c=3;
sum = a+b+c;
printf("%d", sum);
}
通過(guò)上面例子可以三者的區(qū)別:
有一些地方,你可能感興趣:
說(shuō)明:
1960s年代后期,貝爾實(shí)驗(yàn)室對(duì)計(jì)算機(jī)系統(tǒng)的研究進(jìn)入繁盛時(shí)期。MIT、General Electric、Bell實(shí)驗(yàn)室合作的Mutlics項(xiàng)目以失敗而告終(1969年左右)。就是在這個(gè)時(shí)期,Ken Tompson開(kāi)始寫(xiě)Mutlics的替代品,他希望按照自己的設(shè)計(jì)構(gòu)造一個(gè)令人舒服的計(jì)算系統(tǒng)(也就是Unix)。后來(lái)在寫(xiě)出第一個(gè)版本的Unix時(shí),覺(jué)得Unix上需要一個(gè)新的系統(tǒng)編程語(yǔ)言,他創(chuàng)造了一個(gè)B語(yǔ)言。B語(yǔ)言是沒(méi)有類(lèi)型的C,準(zhǔn)確說(shuō)B語(yǔ)言是Tompson把BCPL擠進(jìn)8K內(nèi)存,被其個(gè)人大腦過(guò)濾后的產(chǎn)生的語(yǔ)言。
由于B語(yǔ)言存在的一些問(wèn)題,導(dǎo)致其只是被用來(lái)寫(xiě)一些命令工具使用。恰好在這個(gè)時(shí)期,Ritchie在B語(yǔ)言的基礎(chǔ)上,進(jìn)行了重新的設(shè)計(jì)改良,從而誕生了C語(yǔ)言。
1973年,C語(yǔ)言基本上已經(jīng)完備,從語(yǔ)言和編譯器層面已經(jīng)足夠讓Tompson和Ritchie使用C語(yǔ)言重寫(xiě)Unix內(nèi)核。后來(lái),Unix在一些研究機(jī)構(gòu)、大學(xué)、政府機(jī)關(guān)開(kāi)始慢慢流行起來(lái),進(jìn)而帶動(dòng)了C語(yǔ)言的發(fā)展。
1978年,K&R編寫(xiě)的《The C Programming Language》出版,進(jìn)一步推動(dòng)了C語(yǔ)言的普及。
用一句話總結(jié)就是:對(duì)的時(shí)間、對(duì)的地點(diǎn),出現(xiàn)了對(duì)的人以及工具 (Unix與C語(yǔ)言的關(guān)系,有點(diǎn)像GNU與Linux kernel的關(guān)系,都是互相成就)。
C語(yǔ)言及其標(biāo)準(zhǔn)經(jīng)過(guò)若干次迭代之后,就成了今天大家看到的樣子。其標(biāo)準(zhǔn)中指定了很多C標(biāo)準(zhǔn)庫(kù),而不同的系統(tǒng)都有自己不同的代碼實(shí)現(xiàn)。
當(dāng)然,Linux內(nèi)核中也有實(shí)現(xiàn)了標(biāo)準(zhǔn)C庫(kù)的代碼,下面一起欣賞她的美。
ANSI C共包括15個(gè)頭文件。1995年,Normative Addendum 1(NA1)批準(zhǔn)了3個(gè)頭文件(iso646.h、wchar.h和wctype.h)增加到C標(biāo)準(zhǔn)函數(shù)庫(kù)中。C99標(biāo)準(zhǔn)增加6個(gè)頭文件(complex.h、fenv.h、inttypes.h、stdbool.h、stdint.h和tgmath.h)。C11標(biāo)準(zhǔn)中又新增了5個(gè)頭文件(stdalign.h、stdatomic.h、stdnoreturn.h、threads.h和uchar.h)。
至此,C標(biāo)準(zhǔn)函數(shù)庫(kù)共有29個(gè)頭文件:
https://www.wikiwand.com/zh-sg/C%E6%A8%99%E6%BA%96%E5%87%BD%E5%BC%8F%E5%BA%AB#/%E5%8F%82%E8%80%83%E6%96%87%E7%8C%AE
linux kernel版本:4.18.13
lnux kernel 地址 https://www.kernel.org/
下面列出3個(gè)字符串處理函數(shù) strcpy()、strncpy()、strncat()。代碼出自Linus Benedict Torvalds之手,為什么這么說(shuō)?看代碼頭部注釋?zhuān)€是那個(gè)熟悉的味道stupid。看過(guò)git源代碼的人應(yīng)該也會(huì)知道,git源碼中也有類(lèi)似注釋。
// SPDX-License-Identifier: GPL-2.0
/*
* linux/lib/string.c
*
* Copyright (C) 1991, 1992 Linus Torvalds
*/
/*
* stupid library routines.. The optimized versions should generally be found
* as inline code in <asm-xx/string.h>
*
* These are buggy as well..
*
* * Fri Jun 25 1999, Ingo Oeser <ioe@informatik.tu-chemnitz.de>
* - Added strsep() which will replace strtok() soon (because strsep() is
* reentrant and should be faster). Use only strsep() in new code, please.
*
* * Sat Feb 09 2002, Jason Thomas <jason@topic.com.au>,
* Matthew Hawkins <matt@mh.dropbear.id.au>
* - Kissed strtok() goodbye
*/
// .......omit other......
// ...... here is my love code .....
#ifndef __HAVE_ARCH_STRCPY
/**
* strcpy - Copy a %NUL terminated string
* @dest: Where to copy the string to
* @src: Where to copy the string from
*/
#undef strcpy
char *strcpy(char *dest, const char *src)
{
char *tmp = dest;
while ((*dest++ = *src++) != '\0')
/* nothing */;
return tmp;
}
EXPORT_SYMBOL(strcpy);
#endif
#ifndef __HAVE_ARCH_STRNCPY
/**
* strncpy - Copy a length-limited, C-string
* @dest: Where to copy the string to
* @src: Where to copy the string from
* @count: The maximum number of bytes to copy
*
* The result is not %NUL-terminated if the source exceeds
* @count bytes.
*
* In the case where the length of @src is less than that of
* count, the remainder of @dest will be padded with %NUL.
*
*/
char *strncpy(char *dest, const char *src, size_t count)
{
char *tmp = dest;
while (count) {
if ((*tmp = *src) != 0)
src++;
tmp++;
count--;
}
return dest;
}
EXPORT_SYMBOL(strncpy);
#endif
#ifndef __HAVE_ARCH_STRLCPY
#ifndef __HAVE_ARCH_STRNCAT
/**
* strncat - Append a length-limited, C-string to another
* @dest: The string to be appended to
* @src: The string to append to it
* @count: The maximum numbers of bytes to copy
*
* Note that in contrast to strncpy(), strncat() ensures the result is
* terminated.
*/
char *strncat(char *dest, const char *src, size_t count)
{
char *tmp = dest;
if (count) {
while (*dest)
dest++;
while ((*dest++ = *src++) != 0) {
if (--count == 0) {
*dest = '\0';
break;
}
}
}
return tmp;
}
EXPORT_SYMBOL(strncat);
#endif
#ifndef __HAVE_ARCH_STRLCAT
// .......omit other......
// ...... here is my love code .....
第一次跟同學(xué)一起看這些代碼的時(shí)候,他說(shuō)了一句話:這才叫代碼,其他的都是s-h-X-t。現(xiàn)在回想起,自己在實(shí)現(xiàn)這些代碼時(shí),寫(xiě)了一坨不知道是什么的東西。哎,代碼比代碼要扔~
閱讀他人代碼, 也是一種進(jìn)步、成長(zhǎng)
《史記·廉頗藺相如列傳》記載,廉頗被免職后,跑到魏國(guó),趙王想再用他,派人去看他的身體情況,廉頗之仇郭開(kāi)賄賂使者,使者看到廉頗,廉頗為之米飯一斗,肉十斤,被甲上馬,以示尚可用。使者回來(lái)報(bào)告趙王說(shuō):"廉頗將軍雖老,尚善飯,然與臣坐,頃之三遺矢(通假字,即屎)矣。"趙王以為廉頗已老,遂不用。
經(jīng)歷過(guò)幾十年的風(fēng)雨洗禮,C語(yǔ)言可謂風(fēng)光無(wú)數(shù),這世界上隨處可見(jiàn)它的身影。但是,同時(shí)在一些人眼里,可能覺(jué)得C語(yǔ)言已是暮年(將近50歲)、老矣。如同下圖:
如果你真這樣想,那你就錯(cuò)了。
TIOBE Index for September 2020
https://www.tiobe.com/tiobe-index/
TIOBE 2020-09 編程語(yǔ)言排行榜告訴你,C語(yǔ)言寶刀未老,還是那個(gè)風(fēng)采耀眼的少年。
個(gè)人想說(shuō)的是,只要計(jì)算機(jī)還是基于馮諾依曼體系結(jié)構(gòu),芯片還是基于物理制程。那么,都會(huì)有一片C的天空。因?yàn)椋酪粋€(gè)最接近天空的地方(C是最接近匯編、機(jī)器語(yǔ)言的高級(jí)語(yǔ)言之一)。
任他上層應(yīng)用改朝換代,我(C語(yǔ)言)自巋然不動(dòng)。這就是C,我心中的C語(yǔ)言。
猛然間發(fā)現(xiàn)已經(jīng)到了總結(jié),但是還覺(jué)得仍舊意猶未盡,這并不是我心目中最真實(shí)的那個(gè)她。但是,我還是希望你看完本文之后,能夠多少了解與熟悉C的美與真實(shí)。
最后想說(shuō)的是:縱使千言萬(wàn)語(yǔ)也說(shuō)不盡C語(yǔ)言的重要性,這些文字也僅僅只是冰山一角。
鑒于個(gè)人能力有限,如有問(wèn)題或者缺陷,歡迎指正。
參考資料
在整理的過(guò)程中,部分參考、引用下面鏈接地址內(nèi)容:
[1] https://www.bell-labs.com/usr/dmr/www/index.html 里奇貝爾實(shí)驗(yàn)室主頁(yè)
[2] https://www.bell-labs.com/usr/dmr/www/chist.html C語(yǔ)言發(fā)展史
[3] https://www.bell-labs.com/usr/dmr/www/1stEdman.html Unix Programmer's Manual
[4] https://www.bell-labs.com/usr/dmr/www/bcpl.html Martin Richards's BCPL Manual
[5] https://www.levenez.com/lang/ Computer Languages History
[6] https://www.levenez.com/unix/ Unix History
[7] https://minnie.tuhs.org/cgi-bin/utree.pl The Unix Tree(可以看到很多老系統(tǒng)的源代碼)
[8] https://zh.wikipedia.org/wiki/丹尼斯·里奇
[9] https://www.tiobe.com/tiobe-index/ TIOBE
[10] http://web.eah-jena.de/~kleine/history/ Historic Documents in Computer Science
*請(qǐng)認(rèn)真填寫(xiě)需求信息,我們會(huì)在24小時(shí)內(nèi)與您取得聯(lián)系。