📜 [專欄新文章] 可升級合約介紹 - 鑽石合約(EIP-2535 Diamond standard)
✍️ Kimi Wu
📥 歡迎投稿: https://medium.com/taipei-ethereum-meetup #徵技術分享文 #使用心得 #教學文 #medium
Photo by Evie S. on Unsplash
前言
可升級合約簡單來說是透過 proxy contract(代理合約)來達成,藉由代理合約去呼叫欲執行的合約,若要升級,則把代理合約中的指向的地址換為新的合約地址即可。而執行的方式則是透過 delegateCall,但 delegateCall 不會更動目標合約的狀態。所以要怎麼處理變數,就是一門學問了。
舉例來說,contract B 有個變數 uint256 x,初始值為 0, 而 function setX(uint256),可以改變 x 的值。proxy contract A 使用 delegatecall 呼叫 contract B 的 setX(10),交易結束後,contract B中的 x 依然還是 0。
OpenZeppelin 提出了三種實作方式,可以做到可升級合約,細節可參考 Proxy Patterns,而最終的實作選用了 Unstructured Storage的這個方式,這種方式對於開發較友善,開發時不需特別處理 state variables(不過升級時就需要特別注意了)。而這篇主要是介紹 Diamond standard,OpenZeppelin 的可升級合約就不多做介紹。
USDC V2 : Upgrading a multi-billion dollar ERC-20 token 詳細地介紹代理合約跟變數儲存之間的關係,不了解升級合約的原理,建議先看看。
鑽石合約
名詞介紹
diamond:合約本體,是一個代理合約,無商業邏輯
facet:延伸的合約(實際商業邏輯實作的合約)
loupe:也是一個 facet,負責查詢的功能。可查詢此 diamond所提供的 facet與facet所提供的函式
diamondCut:一組函式,用來管理(增加/取代/減少)此 diamond合約所支援的功能
Loupe
直接來看 loupe的介面,從宣告就能很清楚暸解 diamond合約的實作方式,loupe宣告了一個結構 Facet,Facet結構包含一個地址及 function selector 陣列,所以我們只需要記錄一個 Facet陣列就可以得知這個 diamond 合約有多少個延伸合約及所支援的功能(loupe只定義結構,而實際變數是存在diamon合約中的)。也就是 diamond合約中只記錄延伸合約的地址及其支援的 function selectors,及少數 diamond合約的管理邏輯,並無商業邏輯,因此可以外掛非常非常多的合約上去(就像一個Hub),也就可以突破一個合約只有24K的限制。
// A loupe is a small magnifying glass used to look at diamonds.interface IDiamondLoupe { struct Facet { address facetAddress; bytes4[] functionSelectors; } function facets() external view returns (Facet[] memory facets_); function facetFunctionSelectors(address _facet) external view returns (bytes4[] memory facetFunctionSelectors_); function facetAddresses() external view returns (address[] memory facetAddresses_); function facetAddress(bytes4 _functionSelector) external view returns (address facetAddress_);}
DiamondCut
至於 facet在 diamond合約上的註冊或是修改,就由 diamondCut負責,從以下程式碼可以清楚瞭解其功能(EIP中有規範,每次改變都需要發送DiamondCut事件)
interface IDiamondCut { enum FacetCutAction {Add, Replace, Remove} // Add=0, Replace=1, Remove=2 struct FacetCut { address facetAddress; FacetCutAction action; bytes4[] functionSelectors; } function diamondCut( FacetCut[] calldata _diamondCut, address _init, bytes calldata _calldata ) external; event DiamondCut(FacetCut[] _diamondCut, address _init, bytes _calldata);}
Diamond合約
接下來就是最核心的部分 — diamond本體合約。以下是官方的範例,方法上跟 OpenZeppelin 一樣使用 fallback 函式跟 delegateCall 。
呼叫合約所不支援的函式,就會去執行 fallback 函式,fallback 函式中再透過 delegateCall 呼叫 facet 合約相對應的函式
fallback() external payable { address facet = selectorTofacet[msg.sig]; require(facet != address(0)); // Execute external function from facet using delegatecall and return any value. assembly { calldatacopy(0, 0, calldatasize()) let result := delegatecall(gas(), facet, 0, calldatasize(), 0, 0) returndatacopy(0, 0, returndatasize()) switch result case 0 {revert(0, returndatasize())} default {return (0, returndatasize())} }}
主要的差異在於變數的處理,OpenZepplin 是針對單一合約設計的代理合約(也就是每個合約都有自己的代理合約),所以無法處理單一代理合約儲存多個合約的變數(state variables)的狀況(後有圖例)。先由官方的範例程式來了解是怎麼處理變數的
在官方的範例中,都是以更改合約 owner 為例子
首先看到 DimaondStorage這個結構,結構中的前面三個變數都是在維持 diamond合約的運作(同上面loupe的範例),最後一個變數 contractOwner就是我們商業邏輯中所需的變數。
接著看到 function diamondStorage(),取變數的方式就跟OpenZeppelin 儲存特定變數方式一樣(EIP-1967),是把變數存到一個遠方不會跟其他變數碰撞到的位置,在這裡就是從 DIMOND_STORAGE_POSITION 這個 storage slot 讀取。
在實作上就可以有 LibDiamond1 ,宣告DIMOND_STORAGE_POSITION1=keccak256("diamond.standard.diamond.storage1") ,負責處理另一組的變數。藉由這種方式讓每個 facet合約有屬於自己合約的變數, facet合約間就不會互相影響。而最下方的 setContractOwner 是實際使用的範例。
library LibDiamond {
bytes32 constant DIAMOND_STORAGE_POSITION = keccak256("diamond.standard.diamond.storage");
struct FacetAddressAndSelectorPosition { address facetAddress; uint16 selectorPosition; }
struct DiamondStorage { mapping(bytes4 => FacetAddressAndSelectorPosition) facetAddressAndSelectorPosition; bytes4[] selectors; mapping(bytes4 => bool) supportedInterfaces; // owner of the contract address contractOwner; }
function diamondStorage() internal pure returns (DiamondStorage storage ds) { bytes32 position = DIAMOND_STORAGE_POSITION; assembly { ds.slot := position } }
function setContractOwner(address _newOwner) internal { DiamondStorage storage ds = diamondStorage(); address previousOwner = ds.contractOwner; ds.contractOwner = _newOwner; emit OwnershipTransferred(previousOwner, _newOwner); }
每個 library 處理了一組或多組變數的存取, facet 合約透過 library 對變數做操作。也就是把變數存在diamond主體合約,延伸的 facet合約只處理邏輯,是透過 library 去操作變數。
下面圖中清楚地解釋了 facet合約,function selectors 與變數之間的關係,從最左上這邊有個 facets 的 map,紀錄了哪個 selector 在哪個合約中,例如func1, func2是 FacetA的函式。左下角宣告了變數,每組變數的存取如同上述 library 的方式處理。
https://eips.ethereum.org/EIPS/eip-2535#diagrams
在 diamond的設計中,每個 facet合約都是獨立的,因此可以重複使用(跟library 的概念一樣)
https://eips.ethereum.org/EIPS/eip-2535#diagrams
小結
diamond合約使用不同的設計來達成合約的可升級性,藉由這種Hub方式可隨時擴充/移除功能,讓合約不再受限於24KB的限制,此外充分的模組化,讓每次升級的範圍可以很小。最後,因為跟library一樣只處理邏輯,並無狀態儲存,所以可以重複被不同的diamond合約所使用。
雖然又不少好處,也是有些缺點。首先,術語名詞太多,facet, diamondCut, loupe等等(其實還有好幾個,不過沒有介紹到那些部分,所以沒有寫出來)。開發上不直覺,把變數跟邏輯拆開,若要再加上合約之間的繼承關係,容易搞混,不易維護。最後,gas的花費,在函式的讀取、呼叫,變數的存取、傳遞都會有不少的額外支出。Trail of Bits 專欄中有點出更多的缺陷 Good idea, bad design: How the Diamond standard falls short,不過作者也有反擊 Addressing Josselin Feist’s Concern’s of EIP-2535 Diamond Standard,有興趣的讀者可以自行看看、比較。
為了模組化及彈性,diamond合約在設計上有點太複雜(over engineering),會造成可讀性越差(這點也是Vyper誕生的原因之一),而可讀性越差就越容易產生bug、也越不容易抓到bug,而在defi專案中,一個小小的bug通常代表著大筆金額的損失 😱😱😱。
雖然如此,筆者還是覺得很酷,有些設計的思維仍然可以使用在自己的專案
ref:
EIP 2535
Diamond 實作
Addressing Josselin Feist’s Concern’s of EIP-2535 Diamond Standard
OpenZeppelin upgradeable contract
可升級合約介紹 - 鑽石合約(EIP-2535 Diamond standard) was originally published in Taipei Ethereum Meetup on Medium, where people are continuing the conversation by highlighting and responding to this story.
👏 歡迎轉載分享鼓掌
同時也有126部Youtube影片,追蹤數超過4萬的網紅吳老師教學部落格,也在其Youtube影片中提到,東吳EXCEL VBA與資料庫雲端設計114第6次 上課內容: 01_重點回顧與格式化日期VBA程式說明 02_格式化日期VBA程式說明 03_宣告變數與用Range還原格式 04_VBA插入與刪除空白列 05_年曆VBA串接每個月第一天與其他天與格式化日期 06_黑名單篩選用COUNTIF與定義...
「變數宣告定義」的推薦目錄:
- 關於變數宣告定義 在 Taipei Ethereum Meetup Facebook 的最佳解答
- 關於變數宣告定義 在 軟體開發學習資訊分享 Facebook 的最佳貼文
- 關於變數宣告定義 在 法學博士石人仁 Facebook 的最佳貼文
- 關於變數宣告定義 在 吳老師教學部落格 Youtube 的最佳貼文
- 關於變數宣告定義 在 吳老師教學部落格 Youtube 的最讚貼文
- 關於變數宣告定義 在 吳老師教學部落格 Youtube 的最讚貼文
- 關於變數宣告定義 在 [分享] 混沌四神:陣列、指標、宣告、定義 - 批踢踢實業坊 的評價
- 關於變數宣告定義 在 Sass / SCSS 預處理器- Variables 變數宣告與!global - Roya's ... 的評價
- 關於變數宣告定義 在 009 物件導向的基本觀念影片2 : C++ 教學進階 - YouTube 的評價
變數宣告定義 在 軟體開發學習資訊分享 Facebook 的最佳貼文
--課程已於 2020 年 12 月更新--
本課程是這個領域多年積累的成果,結合了最好的資源、工具和教學內容創建而成的 JavaScript 課程,它將教會你成為高階 JavaScript 開發人員所需的一切知識。
無論你是 Web 開發人員、 React、 Angular、 Vue.js 開發人員(前端開發人員) ,還是 Node.js 後端開發人員,你都將從本課程中受益,因為 Javascript 是這些技術背後的核心。
從這 23.5 小時的課程,你會學到
1. 進階 JavaScript 實踐
2. 物件導向程式設計( OOP )
3. 函數程式設計( Functional Programming )
4. 作用範圍( Scope ) 和執行環境 ( Execution Context )
5. 繼承 + 原型鏈
6. 最新功能 : ES6,ES7,ES8,ES9
7. 閉包( Closures )
8. 非同步 JavaScript + 事件迴圈
9. JavaScript 模組
10. `this` 關鍵字
11. JavaScript 引擎和執行時期( Runtime )
12. 錯誤處理
13. 堆疊溢位( Stack Overflow )
14. 記憶體洩漏( Memory Leaks )
15. 複合( Composition ) vs 繼承( Inheritance)
16. 強制轉型( Type Coersion )
17. 傳址( Pass By Reference ) vs 傳值( Pass by Value )
18. 高階函數( Higher Order Functions )
19. IIFE ( Immediately Invoked Function Expression,一個定義完馬上就執行的 JavaScript 函數)
20. .call(), .apply(), .bind()
21. 直譯器 / 編譯器 / JIT 編譯器
22. 垃圾回收
23. 變數宣告提升( Hoisting )
24. JavaScript 最佳實踐
https://softnshare.com/advanced-javascript-concepts/
變數宣告定義 在 法學博士石人仁 Facebook 的最佳貼文
從來沒有看到如此這般深入地解剖國民黨的文章,一個老國民黨員的心聲。以及相對論述,佩服佩服!
~今後國家何去何從~
撰文者:黃冏堂
自從國民黨敗選後,本不太願意發表言論,但,積鬱仍在,最近天熱,在家避暑,一時心血來潮,就細細整理出滿滿的牢騷,若夥伴們有興趣、有耐心,歡迎分享。
過去國民黨犯的第一個錯誤是無法打敗共產黨,致流落台灣,第二個錯誤是促成了民進黨的茁壯,致淪落在野,第三個錯誤是國人給了國民黨重新執政機會,甚至完全執政,最後又因為失能再度崩解,第四個錯誤,2018年意外的翻轉了地方政權,還產出了蓋世英雄韓國瑜,結果呢?2020沒能奪回中央政權還葬送了韓市長,國民黨到底怎麼了?一寸寸的喪失人心,一次次的政權更替,甚至黨產被步步收繳的歷史教訓,都不能帶來警示、喚回黨魂,重整再戰?現在連惟一的神主牌「一中各表」「九二共識」都成了負值,準備擱置,國民黨未來如何求戰?令人無言。
回顧國民黨政權演繹,自蔣經國離世,李登輝獨攬政權即開始為裂解國民黨勢力與協助民進黨發展不遺餘力,國民黨居然毫無警覺令人不解;連戰接手後,雖有長期政壇歷練,卻是守成有餘、開創不足,建樹甚微的黨主席,國民黨居然放任無為,令人稱奇;至於馬英九則頂著哈佛博士高學歷,也經歷過公職與八年北市長歷練及獲得選民託付兩任八年全面執政機會,可惜,因為「恃才傲物,理念太重、格局太小」,以為自許「全民總統」、高擧「清廉大纛」就足以治國,完全輕忽同黨利益與三教九流的感情交流,立法院又被王金平長期把持,以不作為的多數掣肘執政黨,又放任民進黨少數造亂,進而影響了國民黨執行力,致「令出不了府,法出不了院」,凡事「一籌莫展」,除了讓馬英九成了全民公敵外,還徹底拖垮了國民黨,馬英九這位迂腐到能讓藍營寧願自廢武功、棄械投降與無恥度自我牽扯的立法院王前院長,還能讓國民黨視若珍寶,令人無言;當朱立倫臨危受命,聲勢低迷亦如強弩之末的黨與黨高層各個只求明哲保身,難得洪秀柱不畏譏讒挺身而出,卻遭抽樑換柱,結果,朱立倫領軍的選戰兵敗如山倒,令人咋舌;爾後的吳敦義不遑多讓,看好的一局棋,居然玩到滿盤皆輸,坐實了「國民黨昏庸無能」的罪名,令人髮指;更可議的是,多位領導者在位的表現總是「利用」國民黨多於「經營」,難怪無法建立中心思想、統一戰力,以致任人宰割,另外,藍營還有位永遠的宋省長楚瑜先生,這位才思敏捷、能力過人卻桀驁不馴的高人,近二十年總統大選幾乎無役不與的韌性,成了綠營裂解藍營團結的重要棋子,令人作嘔;綜觀前論,李登輝之後的數十年,這些歷任黨主席與未曾當過黨主席的高層與國民黨發展史一直息息相通,國民黨的敗能說「與他們無關」?現任黨主席江啟臣能脫穎而出,是老世代被嫌棄,至於,在百廢待舉的黨內能有多少作為,黨員確實難有太多期待,因為,除了國民黨羸弱外,台灣的環境已有太多無法掌控的變化,均非自稱「溫良恭儉讓」的國民黨所能駕馭,比如:
學生:讀一點書,懂一些小知識,透過網路片段、看懶人包,就以為盡知天下事,對事件全程、全景、他人觀點均不屑一顧,未能對父母盡孝、對家庭盡責,亦未對社會有所貢獻,動輒以正義之師衝撞義理、法制,那種狂妄、無知行逕,還自以為是英雄,更甚者,一群盲從者在政客調教、輿論的推波助瀾下,讓猖狂更是無限上綱,國民黨能掌控得了?
選民:現在的民主就是民進黨做主,愛台灣就是愛民進黨認同的台灣價值,至於台灣陷入藍綠、族群、階級、世代鬥爭,政經發展停滯不前等均非選民關注的大事,現階段選民要的是反中與腥羶大戲,猶如台灣的本土劇,鎮日呈現背離事實、勾心鬥角、逞兇鬥狠、傷風敗俗,使壞目標甚至指向家人、朋友、職場、情敵、政敵,那種「不耍狠」不足以出頭的手法令人不寒而慄,什麼是國人正確的生活價值觀?已無人在意,國民黨有能力改變嗎?
議會:國會殿堂、地方議會諸委員、議員,明裡是為國效力、為民服務,暗裡則是沆瀣一氣、朋比為奸、坐室分贓,各個還能道貌岸然的在殿堂上扒糞掀臭、謾罵羞辱,視政事如草芥、視官員如禁臠,予取予求,現立院民進黨的多數,更讓國會霸凌亂象發揮到極致,誰能抗衡?試想,以國民黨過去在國會擁有絕對多數時能被無極限的霸凌,如今屈居少數,若說有能力改變,有人會相信嗎?
輿論:誰人不知傳媒善以聳動標題,達成聚焦,藉腥羶話語推波助瀾,博取版面,萬年本土劇為炒熱收視率常以低俗手法,鎮日毀損生活價值觀為樂事,至於「名嘴之流」亦少思正義公理,習以偏私、妄言,製造對立,尤其,在民進黨的主導下,「網軍出征,寸草不生」更成台灣另一種禍源,請問,國民黨有本事翻轉嗎?
國民黨:檯面上的連戰、馬英九、朱立倫、洪秀柱、吳敦義等歷任黨主席,除了馬英九參選未嚐敗績外,其他的都是輔選或參選的輸家,不要說勇於承擔,連表態都是虛軟的,現黨員均已老邁且士氣低盪谷底,少席次的黨籍立委也無「論述」與「攻堅」之力,各層級接班人又青黃不接,前途乖舛,如今,民進黨縱然失政產生民怨,也難以轉為國民黨所用,黨產會又困住國民黨,新任黨主席江啟臣在內憂外患下,又能有多少作為?
民進黨:在全面執政之後,依過往經驗、堅固的基本盤與勢如破竹的網軍,還有卓越的選戰技倆,台灣已如囊中物,不再需要虛掩謙卑之事,未來想幹什就幹了,現今的國民黨已被鬥得氣若游絲,名存實亡,不知國民黨是否學到了教訓?可有起死回生之道。
國軍:中共對收復台灣的野心是眾所周知,為確保國家安全,政府理應整軍經武、勵精圖治才是,事實上,年輕世代對服役視為畏途,軍人地位亦一落千丈,護衛疆土的國軍又因承平日久,輕本務,重雜務,致高層以行政績效掛帥,為求官,趨炎附勢,基層則察言觀色,被動苟且,嚴謹的軍隊連軍法都不可得,還談何謂軍務?軍規?更不要說軍魂了,更甚者,軍人為國家奉獻一生的退休保障都被惡名化,朝不保夕,民進黨當家,無論如何進行軍改,自有其心思,不予置評,至於國民黨任由軍人被糟蹋卻毫無阻滯之力,無論現役或退役軍人還能對國民黨有所期待?
世事:新冠肺炎肆虐、香港反中、台灣獨台、中印邊界紛擾、南北韓叫陣、釣魚台事件、美國的興風作浪,讓世局充滿了一觸即發的變數,民進黨已藉由全面執政準備走自己的路了,反觀國民黨,連自己論述的神主牌「九二共識」都準備棄置了,還有其他能力參與、承責嗎?
結語:
台灣有不同族群、不同信仰、不同政黨、不同階級、不同行業、不同世代等差異,我曾相信這些人是愛這個土地,會努力為台灣的未來付出,同樣的,任何執政黨也會帶領國家走上康莊大道,遺憾的,政黨卻是以奪權為目標,政客則以滿足個人私欲為優先,為謀奪金錢、利益、權勢,無不費盡心思、用盡手段,尤其,民進黨更是箇中高手,經過長期殺伐,「民進黨世代」不再是崛起,而是全面強力登場,更卓然有成的掩埋了國民黨這個百年老店,正式宣告進入「民進黨」的輝煌時代;話說至此,還真是語重心長,尤其,看著依附已久的政黨衰敗,還落井下石的數落,那種無奈終非所願,今日,我已是近七十的老翁,早期曾幻想中國一統好夢,可惜,未能圓夢,晚期則身不由己,得在新世代引領下為獨台追夢,一生兩夢情境大不相同,既然時勢使然,也是台灣住民的新選項,我可以坦然面對並接受未來衍生的後果,暫時安於生活與看輕世事,只是,偶爾想到國民黨的沒落與下一代要迎接那麼多不安的變數,總是心有戚戚焉。
成大同學晚安。我知道你憂國憂民,這是我薄薄的淺見,您參考參考。
是一個新的概念!不是明朝,不是滿清,不是民國,是 中華民國台灣!這總共四個朝代,(明白嗎?明白嗎?明白嗎?)所以綠朝早就準備好了⋯⋯台灣人南洋蠻夷化,有綠色政客法理論述,不學習中華文化,還滅中華文化,更改課綱,用教育來洗腦,用街頭暴力帶領悲情選舉,侵吞蠶食,府院黨軍情警調,文化總會,地方農漁會水利會鄉鎮民代各地區長,所有國營事業,轉投資的各肥肉公司,大法官會議,等等等。所以⋯這是改朝換代 改朝換代 改朝換代。所以宣誓就職是騙你的,街頭抗議就用油壓剪對付,剪個手指算什麼?有上校摔死絕對不讓你英雄化,立刻發動所有宣傳力量把事情污名化,現訴求憲法?門都沒有,大法官全部綠化。想訴求民意?完全不可能,名嘴,媒體,1450,誰有能力抵禦。監察院呢?本來就是個雞肋,現在派滿提滿,分贓剛剛好。古時改朝換代殺進城,搶糧搶錢搶女人,規矩我訂,官位我派,天下我獨享,看看高雄市派了多少中央官,口水哥從上尉直升少將誰說不可以。中央警衛官記個大過而已,升個少將誰說不可以?目地就是要告訴所有有志於官癌的人,來跟著綠營效忠綠營的人,ㄧ定會有回報率的。民國的官箴概念沒有了,四維八德也沒了,綠陣營就是不要,看懂了嗎?所有價值全部推翻,通通不算,換綠的來定義,這是另一個國家,另一個朝代,綠朝只是懼於中共,不敢台獨,非綠營的政客想要得江山?恐怕只有政變ㄧ途,不信?大家等著看,綠魔爪ㄧ定更狠,緊緊的控制台灣,想靠中共武統,那肯定是民族悲劇。未來會如何發展呢?回顧歷史,其實早就告訴我們,中華文化ㄧ定會繼續,民族ㄧ定會強盛,歷史的共業中國人是有智慧解決的,願綠營能讓台灣島上的人民在這過程中,安居樂業,傳宗接代,與中華民族共存共榮,騙 來的江山是短暫的,綠陣營政客看遠一點吧!否則將來報應來時,可別怨天尤人,聊表言盡於此。至於國民黨???應該氣數已盡,可以出殯了。
變數宣告定義 在 吳老師教學部落格 Youtube 的最佳貼文
東吳EXCEL VBA與資料庫雲端設計114第6次
上課內容:
01_重點回顧與格式化日期VBA程式說明
02_格式化日期VBA程式說明
03_宣告變數與用Range還原格式
04_VBA插入與刪除空白列
05_年曆VBA串接每個月第一天與其他天與格式化日期
06_黑名單篩選用COUNTIF與定義名稱與篩選
07_黑名單篩選用VBA篩選與複製
完整教學
http://goo.gl/aQTMFS
吳老師教學論壇
http://www.tqc.idv.tw/
教學論壇(之後課程會放論壇上課學員請自行加入):
https://groups.google.com/forum/?hl=zh-TW#!forum/excel-vba-114
懶人包:
EXCEL函數與VBA http://terry28853669.pixnet.net/blog/category/list/1384521
EXCEL VBA自動化教學 http://terry28853669.pixnet.net/blog/category/list/1384524
課程簡介
五大類函數與自訂函數
一、文字和資料函數
二、邏輯函數
三、日期和時間函數
四、數學和三角函數
五、檢視和參照函數
其他綜合範例
上課用書:
Excel VBA一點都不難:一鍵搞定所有報表
作者: Excel Home
出版社:博碩
出版日期:2013/06/26
定價:380元
超圖解 Excel VBA 基礎講座
作者: 亮亨/譯 出版社:旗標
出版日期:2006/05/15 定價:420元
日本Amazon網站同類書籍銷售No.1
吳老師 110/4/12
函數,東吳進修推廣部,自強基金會,程式設計,線上教學excel vba教學電子書,excel vba範例,vba語法,vba教學網站,vba教學講義,vba範例教學,excel vba教學視頻
變數宣告定義 在 吳老師教學部落格 Youtube 的最讚貼文
東吳EXCEL VBA與資料庫雲端設計114第6次
上課內容:
01_重點回顧與格式化日期VBA程式說明
02_格式化日期VBA程式說明
03_宣告變數與用Range還原格式
04_VBA插入與刪除空白列
05_年曆VBA串接每個月第一天與其他天與格式化日期
06_黑名單篩選用COUNTIF與定義名稱與篩選
07_黑名單篩選用VBA篩選與複製
完整教學
http://goo.gl/aQTMFS
吳老師教學論壇
http://www.tqc.idv.tw/
教學論壇(之後課程會放論壇上課學員請自行加入):
https://groups.google.com/forum/?hl=zh-TW#!forum/excel-vba-114
懶人包:
EXCEL函數與VBA http://terry28853669.pixnet.net/blog/category/list/1384521
EXCEL VBA自動化教學 http://terry28853669.pixnet.net/blog/category/list/1384524
課程簡介
五大類函數與自訂函數
一、文字和資料函數
二、邏輯函數
三、日期和時間函數
四、數學和三角函數
五、檢視和參照函數
其他綜合範例
上課用書:
Excel VBA一點都不難:一鍵搞定所有報表
作者: Excel Home
出版社:博碩
出版日期:2013/06/26
定價:380元
超圖解 Excel VBA 基礎講座
作者: 亮亨/譯 出版社:旗標
出版日期:2006/05/15 定價:420元
日本Amazon網站同類書籍銷售No.1
吳老師 110/4/12
函數,東吳進修推廣部,自強基金會,程式設計,線上教學excel vba教學電子書,excel vba範例,vba語法,vba教學網站,vba教學講義,vba範例教學,excel vba教學視頻
變數宣告定義 在 吳老師教學部落格 Youtube 的最讚貼文
東吳EXCEL VBA與資料庫雲端設計114第6次
上課內容:
01_重點回顧與格式化日期VBA程式說明
02_格式化日期VBA程式說明
03_宣告變數與用Range還原格式
04_VBA插入與刪除空白列
05_年曆VBA串接每個月第一天與其他天與格式化日期
06_黑名單篩選用COUNTIF與定義名稱與篩選
07_黑名單篩選用VBA篩選與複製
完整教學
http://goo.gl/aQTMFS
吳老師教學論壇
http://www.tqc.idv.tw/
教學論壇(之後課程會放論壇上課學員請自行加入):
https://groups.google.com/forum/?hl=zh-TW#!forum/excel-vba-114
懶人包:
EXCEL函數與VBA http://terry28853669.pixnet.net/blog/category/list/1384521
EXCEL VBA自動化教學 http://terry28853669.pixnet.net/blog/category/list/1384524
課程簡介
五大類函數與自訂函數
一、文字和資料函數
二、邏輯函數
三、日期和時間函數
四、數學和三角函數
五、檢視和參照函數
其他綜合範例
上課用書:
Excel VBA一點都不難:一鍵搞定所有報表
作者: Excel Home
出版社:博碩
出版日期:2013/06/26
定價:380元
超圖解 Excel VBA 基礎講座
作者: 亮亨/譯 出版社:旗標
出版日期:2006/05/15 定價:420元
日本Amazon網站同類書籍銷售No.1
吳老師 110/4/12
函數,東吳進修推廣部,自強基金會,程式設計,線上教學excel vba教學電子書,excel vba範例,vba語法,vba教學網站,vba教學講義,vba範例教學,excel vba教學視頻
變數宣告定義 在 Sass / SCSS 預處理器- Variables 變數宣告與!global - Roya's ... 的推薦與評價
global、!default 標誌定義 ... 前面我們有提到SCSS 的變數就如同JavaScript 用 let 宣告的變數,與 const 宣告的常數不同, let ... ... <看更多>
變數宣告定義 在 009 物件導向的基本觀念影片2 : C++ 教學進階 - YouTube 的推薦與評價
... 新影片上傳時, 會接到通知之外, 更可以鼓勵我, 讓我有持續錄製的動力) 影片內容: 何謂類別? 物件 變數 的 宣告 與使用- 009 物件導向的基本觀念影片2. ... <看更多>
變數宣告定義 在 [分享] 混沌四神:陣列、指標、宣告、定義 - 批踢踢實業坊 的推薦與評價
陣列與指標,宣告與定義,就像桂綸鎂與柯佳嬿一樣,總是這麼容易讓人搞混。
本文列出一些與九九乘法表一樣,值得記下的觀念,總共 12 條而已。
背起來
(1)
宣告:介紹名稱給 Compiler,使編譯器知
道這個 name 及其 type。
背起來
(2)
定義:決定 name 的內容,如函數定義。
背起來
(3)
宣告可以有多次,定義只能有一次。
背起來
(4)
在 C/C++ 中,宣告就是定義。
--
例外狀況:
函數原型宣告、用 extern 宣告的外部
變數、類別宣告內的 static 資料成員、
class forward declaration...
※ 詳見:https://msdn.microsoft.com/en-us/library/0kw7hsf3.aspx
背起來
(5)
初始化:變數定義時,給予預設值。
※ int i = 4; 表示宣告/定義型態為 int 的變數 i,並初始化為 4。
int j; 宣告/定義變數 j,但沒有進行初始化。
在 VC 環境下,變數 j 的值將被編譯器定義為 0xCC。
若在後面使用 if (j == 2) 之類的運算,在 Debug 組態下,執行後跳出
錯誤:Run-Time Check Failure - The variable 'j' is being used
without being initialized.
j = 5; 不代表初始化,這是 assignment (賦值)。
比如 class CMyWnd wnd1;
↑已呼叫預設建構子,已完成物件初始化。
比如 CMyWnd::CMyWnd() : xCoord(100) { xCoord = 300; }
↑其中 xCoord 被初始化為 100,然後才被賦值為 300。
而 yCoord 未被初始化。
TIP:宣告變數的時候,總是進行初始化。
背起來
(6)
在 C99 及 C++ 標準下,允許變數宣告不必
放在 statements 之前。但此時禁止 goto
跳過任何變數宣告。
※ 一旦 goto 跳過變數宣告,就會連帶使得對該變數的引用,都未經過初始化。
在 VC 2008 SP1 下,這樣寫可以通過編譯,
但會警告:「warning C4700: 使用了未初始化的區域變數」。
TIP:非要用 goto 的情況下,必須自己避開變數宣告,對編譯器別指望太多。
詳見:https://www.jeffhung.net/blog/articles/jeffhung/1245/
背起來
(7)
若 P 為陣列,則 P 與 &P 有相同數值。
但兩者 Data Type 不同。
背起來
(8)
若 xType 為指標,則 xType + 1 之值,
是由 xType 指向目標的 Data Type 決定。
※ 設 xType = 0x1000; (在 x86 32-Bit 平台下,其他平台請洽處理器製造商)
若 xType 為 char * 則 xType + 1 = 0x1001;
若 xType 為 double * 則 xType + 1 = 0x1008;
若 xType 為 char (*)[10] 則 xType + 1 = 10 * sizeof(char) = 0x100A;
若 xType 為 char (*)[2][10] 則 xType + 1 = 0x1014;
背起來
(9)
xType[2] 的運算,等於 *(xType + 2)。
第一階段:計算 xType + 2 的位址
第二階段:對上述位址做 dereference(*)
背起來
(10)
argument = 實際參數 (Actual Parameter)
parameter = 形式參數 (Formal Parameter)
背起來
(11)
傳陣列當 argument 時,函數的「形式參數」
之宣告,有以下兩種形式:
形式1:最左維度改成 [],其餘不變
形式2:pointer to arr[0]
背起來
(12)
陣列識別項在 expression 中,會自動轉型成
指標:pointer to arr[0]
--
例外狀況:
sizeof、address-of(&)、參考的初始化
※ 詳見:https://msdn.microsoft.com/en-us/library/266kd92t.aspx
_______________________________________
關於 (11) 中的兩種形式,補充說明於本段。
假設要傳進函數 foo 的 argument 為 int arr[3][4][5],
則函數 foo 的可用宣告如下。
foo(int arr2[][4][5]); 就是所謂的形式1。
foo(int (*arr2)[4][5]); 就是所謂的形式2,亦即 pointer to arr[0]。
因為 arr 是三維陣列,所以 arr[0] 也就是 *(arr+0) 是一個二維陣列,且其
型態為 char [4][5]。故指向 arr[0] 這個二維陣列的指標,是為 char (*)[4][5]。
根據 (12) 所述,arr 這個陣列識別項,在運算式中會自動轉型成 pointer to arr[0]。
這英文不太好記,我的記法是:
看到陣列名稱 arr,就無條件當成指標。
因為 * 運算子的優先權不是最高,所以立刻加上括號,變成 (*arr)
最後再決定「指向的型態」一定會是少掉最左維度後的樣子,即 int [4][5]
合成後就是 int (*arr)[4][5] 型態了。
以 main 函數為例,其形式參數的宣告,通常是 char **argv 或者是 char *argv[]。
根據以上觀念,可以知道 argv 的實際參數會是一維陣列,每個元素為 char * 型態。
如果實際參數是二維陣列,比如 char [10][20],則 argv 會宣告成
char argv[][20] 或 char (*argv)[20] 才對。
_______________________________________
真的可以把「陣列名稱」當成「指標」嗎?
___________________
陣列名稱在運算式內,本來就會自動轉型成,上述的那種指標。
在 (12) 中也提過,有三種例外:sizeof、address-of、參考初始化。
要注意的只有 sizeof(arr) 跟 &arr。
若陣列 arr 真的完全等同於指標,那 sizeof(arr) 應該等於 4,
且 &arr 的值不會等於 arr 的值。
那我們寫的時候,以及編譯器在處理的時候,都一定知道 arr 在目前函數內的宣告型態
為 int arr[3][4][5] 陣列,所以不至於傻到在這兩種運算下,還把他當成指標看。
當我們把 arr 傳進函數 foo,使用 int (*arr2)[4][5] 去當形式參數接收時,
本來就知道此時的 arr2,其型態是一個指標,只是收藏了當初那個 arr 的位址而已。
所以在 foo 內做 sizeof(arr2) 與 &arr2 自然有不同的結果。
所謂無條件將陣列名稱當成指標來用,應該是說 arr[1][2] 或 arr2[1][2]、
arr + 3、arr2 + 3 這些運算的結果一定會相同,不要無限上綱到 sizeof、
address-of 去就不會出事了。
_______________________________________
[學越多想越多] 組合語言觀點下,陣列名稱跟指標明明就不同,為什麼 C 可以亂用?
___________________
編譯器默默承受...
C/C++ 的撰寫者,可以無腦的把 arr 跟 arr2 當成一樣的東西,
即便一個是陣列,一個是指標也沒差。聰明的 Compiler 會依據資料型態而做調整。
以 arr + 1 與 arr2 + 1 為例:
因為 arr 是陣列,是本地的區域變數,所以它的起始位址,會固定是 ebp - 0xF8 這
類地址,也就是與 ebp 暫存器相隔固定 N 位元組的地方,此例 N = 248。
而 arr2 是 foo 內唯一的形式參數,他的存放位址會固定在 ebp + 0x8。
在計算 arr2 + 1 時,要先到 ebp + 0x8 取出裡面存放的位址,其實就是 &arr。
004113E0 8B45 08 mov eax, dword ptr ss:[ebp+8]
其指令如上所述,其中 004113E0 是 EIP 位址,而 8B45 08 是機械碼,
最後當然就是反組譯後的指令。上面這行指令會到 arr2 裡面取出 &arr 的值,然後
因為指標型態是 int (*arr2)[4][5],所以接著還要加上 20 * 4 (add eax, 80),
最終在 eax 暫存器內,才能得到 arr2 + 1 的值。
在計算 arr + 1 時,直接用 lea 指令,把 ebp 暫存器目前的值減掉 0xF8,就可以
得到 &arr 的值。但因為 arr + 1 不過隔了 80,所以直接改成用 lea 指令,計算
ebp - 0xF8 + 0x50,也就是用 lea 指令算 ebp -0xA8 的結果即得到 arr + 1。
※ 不管是 arr + 1 或 arr2 + 1 得到的值都一樣,但底層的計算方式卻不同,
一切都由 Compiler 去操心就好。
計算 arr[1] 與 arr2[1] 的背後:
就 C/C++ 觀點來看,兩者得到的東西都一樣,沒有什麼好多想的,可以關電視了。
但私底下,Compiler 到底瞞著我們偷偷做了什麼事呢?
根據 (9) 可以知道:arr[1] 等於 *(arr + 1),及 arr2[1] 等於 *(arr2 + 1)。
實際反組譯可以發現,其實 arr[1] 跟 arr + 1 的 CPU 指令根本一樣。
而 arr2[1] 與 arr2 + 1 也是用一樣的 CPU 指令在應付。
那是因為當 Compiler 發現:
Dereference (*) 後的目標,其資料型態為陣列時,一律省略取值動作。
換句話說,因為 arr[1] 是一個陣列,所以 * 運算不用做了。
假設有 short blahA[10];
則 blahA[3] 的計算,會先求出 blahA + 3 這個位址,然後真的到
該位址去取 2 Bytes 來: mov ecx, word ptr[ blahA + 3 的位址 ]
假設有 char *blahB[20];
則 blahB[3] 也是同理,在最後會執行取值運算:
mov eax, dword ptr[ blahB + 3 的位址 ],此時 eax 的為 pointer to char。
※ 在以上組合語言中,word 指 2 Bytes,dword 指 4 Bytes,所以到某個記憶體
位置去讀取兩位元組資料,範例指令為:mov ecx, word ptr[ 記憶體位址 ]
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 124.8.138.96
感謝您無私提出意見。
之所以寫成這樣,是為了讓文章好寫。
一開始設定的讀者對象,只考慮學程式有段時間的版友。
大家都是寫過點程式的人,這種筆記、條列型格式,你們看得快,我也省時間。
稍微點一下,其餘的讓大家發文互相討論交流,應該就能解決。
如果是我會回答的問題,我會幫忙回答。
※ 編輯: purpose 來自: 124.8.137.91 (09/15 15:33)
... <看更多>