看板 C_and_CPP 關於我們 聯絡資訊
※ 引述《windows2k (程式宅 <囧>)》之銘言: : 我又來問問題了... : 作業四裡面有個範例 : #define f(x) 1 x : #define g(x) 2 x : g(f)(g)(3) : 推導最後的結果是 2 1 g(3) : 我的問題是為什麼最後的g不被替換掉...雖然有寫解釋但我看不懂 orz : 試了一下gcc跟clang : 這範例的結果都是 2 1 2 3 : 有人可以幫忙解釋一下嘛?謝謝 PA4大概是目前五個PA中最難看懂到底要做什麼的... macro部份的標準真的是一團亂,因為他是經過40年的大家亂加東西後 才被硬寫出標準來的。 這部份有很多implemention-defined behavior,所以和gcc不一樣很正常 //////////////////////////// 第一個規則是: 「如果macro代換過程中遇到跟該macro同名的token,該token不會被代換 而如果接下來的多層代換中再度碰到與這個macro同名的token,也不會代換」 課程中定義所為的多層代換(nested replacement): 如果觸發Y的token為X的代換結果,那XY互相就為多層代換 以黑名單的方式實做可以將上面翻譯成 「所有macro代換出來的token,都會黑名單該macro的名稱 同時繼承觸發此macro的token的黑名單」 所以: //token正下方為該token的黑名單內容 g(f)(g)(3) => //代換g(f) 2 f(g)(3) g g //2和f由g產生因此黑掉g => //代換f(g) 2 1 g(3) g g g f f //1和g由f產生,因此黑掉f //同時繼承f的黑名單[g] 接著g(3)因為g已經被黑名單了所以不會進行代換 ////////////////////////////////////////// 第二個規則是: 「如果一個token曾經因為多層代換而沒被代換,則該token就算經過參數代換也 永遠不會被代換」 函數式的macro的參數會先被單獨抽出來,代換完後再放回macro 在放回macro前,他的黑名單會先被清乾淨。 但是在過程中因為黑名單而沒被代換的token會被留下終生不得代換的記號 也就是水桶期間發文所以被BAN IP 例如 #define z z[0] #define f(x) 1 x f(z) //// f(z) => 抽出參數z,單獨代換 f(x:= z ) => f(x:= z[0] ) zzzz => z[0]是代換產生物,因此重新套macro一遍 f(x:= z[0] ) zzzz * //z被黑名單又想被代換,因此加上不得代換標記 => 代換f(x),把x的黑名單清乾淨 1 x x:= z[0] f f * => 放入x 1 z[0] f ffff * =>重新套macro 1 z[0] f ffff * //z被標為不得代換,因此沒被代換 -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 118.168.88.7
windows2k:謝謝 04/26 12:27
remmurds:說真的 能不用macro就盡量不要用它 04/27 21:39
suhorng:@remmurds: 可是作業不得不弄macro XD 04/27 23:16
azureblaze:這個作業告訴我們: 去你的macro 04/27 23:38