[閒聊] 為什麼 C 語言不提供指向虛無的指標

作者: Hazukashiine (私は幸せです)   2017-10-10 13:28:03
在 C 語言裡面對 NULL 取值是非法的
通常伴隨的是發生 segmentation fault
而這通常也跟 CPU 的指令集實作有關
因為編譯器會將對 NULL 取值的程式碼
假定 NULL 就是常數數值 0 的情況下
編譯成類似 movl $10, 0x0 等的指令
因此 CPU 在處理相關指令的時候
豎立 flag 觸發 OS 處理是可以預期的
但是既然 C 語言被定調成高階語言
為什麼不提供一些抽象一些的語意
像是對「虛無指針」取值是代表忽略的意思
比如說 VACANT 代表「虛無指針」
則 void *arr[] = {VACANT, VACANT};
*arr[1] = (uintptr_t)12345;
代表什麼事(包含副作用)都不會發生
感覺對空虛取值不發生作用非常實用
就像指令集幾乎都會有 NOP 一樣
表面上看起來沒什麼用
但是卻能在不少 corner cases 發生作用
NOP 可以去解決 hazard 的問題
VACANT 可以解決不少指針初始化的問題
可以減少程式設計所需的 sentinel value
還在特定的時候能讓程式減少無謂的判斷式
基本上我還沒想到什麼負面的影響
我的問題是為什麼不設計類似的指針?
類似 /dev/null 的概念
看起來沒什麼用 但是卻大大有用 XD
作者: qsort (Cos)   2016-07-12 15:52:00
: 我猜,該檔案被鎖住了,所以git無法access,才會報錯: 建議用.gitignore把這類temp檔ignore掉,不要上到git。
作者: gitignore (git)   2016-07-13 04:41:00
有人叫我?
作者: jerryh001   2017-10-10 13:38:00
C語言的特色就是更快,還要更快 額外的動作都浪費時間
作者: AstralBrain   2017-10-10 13:45:00
那你希望int x = *VACANT; 的x的值是多少未初始化的垃圾值? 這樣跑到後面會出現更多問題還不如在一開始直接死如果等號左邊是複雜的c++ class那更無解了所以其實你要的不是VACANT, 而是對void做各種運算..?那 int *ptr = (int*)VACANT; 會發生什麼事其實我想問的是你允不允許VACANT轉型成其他指標 XD如果允許的話就回到我一開始的問題*(int*)VACANT 要segfault還是要NOPsegfault => 跟null有87%像, nop => 跑到後面更慘實作好處理 問題是要怎麼限制vacant只能write-only現在你要的功能應該可以用c++自己做一個出來在smart pointer外面再包一層之類的可以先自己試用看看 XD
作者: CoNsTaR ((const *))   2017-10-10 14:27:00
就算這樣比較好編譯器也做不到啊因為很多情況下編譯器沒辦法知道一個變數(當然也包含指標變數)的值例如假設有個不可判定的問題,它有兩種可能的答案(例如是、否)寫一個試圖解決這個問題的函式,如果答案是是,那就將指標 assign 為 NULL,否則 assign 為其他值那如果編譯器要知道這個指標的值為何,就必須要先知道這個問題的答案所以很明顯這樣的構想是不能成立的或者說,那個問題的答案是一個整數,然後你把答案轉型 assign 給指標,那編譯器就得知道它的答案是否為零
作者: LPH66 (-6.2598534e+18f)   2017-10-10 15:50:00
你在講的不就是在編譯時期擋下來嗎?那你又提執行時期的數值做什麼...然後就是因為編譯時期擋不下來 (理由如上述) 才會變成 UB硬解那就跟 C 語言無關啦, 其他人又不用你的特別硬體然後 (雖然離原題離版題都很遠) 你或許可以看看 MIPS它的 $0 這個 register 是常數零, 讀它得零, 寫它是 NOP雖然這是 register 不是位址但大概跟你想要的東西沾了個邊
作者: Lipraxde (Lipraxde)   2017-10-10 19:15:00
不是應該先設計指令集在用硬體實作嗎?
作者: sppmg (sppmg)   2017-10-10 19:33:00
C不是一直被稱作中階語言嗎 ^_^
作者: chchwy (mat)   2017-10-10 19:49:00
Objective-C提供了喔
作者: Bencrie   2017-10-10 20:01:00
x86 realmode 就不會噴 segfault 啦但是改 IVT 會發生什麼事就不知道惹
作者: lc85301 (pomelocandy)   2017-10-10 21:17:00
好了大家別吵了都來寫Rust吧(誤
作者: PkmX (阿貓)   2017-10-10 22:10:00
好奇你的VACANT要怎麼減少sentinel value和減少判斷
作者: AstralBrain   2017-10-10 22:22:00
仔細一想反正你只是要一塊write-only的垃圾位址那 void* vacant = new char[4096]; 就好啦 XD是不是真的nop也不是很重要
作者: CoNsTaR ((const *))   2017-10-10 23:35:00
其實 Idris、Agda 的編譯器可以做到你想的東西,只是它們是和 C 非常不同的語言我是覺得 C 應該無法(也不需要)做到這樣的事情啦
作者: azureblaze (AzureBlaze)   2017-10-11 00:19:00
沒有痛覺神經就不怕被刀砍了程式寫錯會crash是好事debug寫入資料遺失聽起來就超好玩
作者: james732 (好人超)   2017-10-11 00:59:00
其實有點好奇其他語言(如rust)怎麼解決這問題
作者: PkmX (阿貓)   2017-10-11 01:26:00
痾你還是沒有解釋如何用VACANT避免circular buffer的SV和判斷啊 有了VACANT不用判斷就可以知道buffer滿了?你一開始裡面都塞VACANT那你push的東西到底寫到哪裡去了?
作者: CoNsTaR ((const *))   2017-10-11 02:10:00
可是 C 預設是不做 prefill 的啊,這不符合 C 的精神我覺得你這樣又 prefill 拖效能,遇到錯誤又讓他蒙混過去當作沒發生,而且又不直覺,真心覺得不是什麼好辦法現在其他語言處理這種問題不拖效能而且又能在編譯時期處理完的通常都是用 depnedent types 吧…像 rust 也有用的 linear types 可以知道哪些東西存取過了,哪些還沒,和存取次數,而且也是編譯時期就檢查完,也是一種方法
作者: PkmX (阿貓)   2017-10-11 03:00:00
你那樣寫的意思是前面幾個iteration *(queue[index]) 因為pointer 是 VACANT 所以值寫進去被 discard 也是合理的?
作者: Hazukashiine (私は幸せです)   2017-10-11 03:03:00
嗯嗯 我希望是這樣沒錯
作者: PkmX (阿貓)   2017-10-11 03:22:00
這樣的話 最直覺的方式還是就分配一個垃圾位置當初始值就好或是既然你知道最後SV會不見 就分成兩個版本 前面的需要檢查而後面的phase已知SV不存在 就不需要檢查 當然比較進階的type system可以幫你紀錄你的資料結構裡面是否還存在SV(e.g. phantom type) 不過這個已經扯遠了當然程式語言或是硬體是否要支援這種blackhole的位置我想實作上都是沒有問題的 只是有沒有必要為了這個例子而去複雜化語言的spec或是硬體的ISA罷了另外多了一個branch在整個loop中+有分支預測的CPU執行下所造成的效能影響多寡也是一個要探討的問題
作者: kaneson (Lance)   2017-10-11 13:00:00
不會叫的bug才是最難找的
作者: dou0228 (7777)   2017-10-11 17:10:00
同意樓上,忽略是一個最糟糕的寫法,不應該這樣做
作者: samuelcdf (溫泉龜)   2017-10-12 15:36:00
看起來好像只是把programmer的責任丟給compiler一樣就跟很多有自動記憶體配置回收的語言一樣, 寫的不好,只是延後整個軟體掛掉的時間一樣. 而且更難除錯.
作者: uranusjr (←這人是超級笨蛋)   2017-10-14 02:12:00
只要忽略的邏輯清楚行為直觀就不糟糕, 斷言「不應該」是不太好...其實也有很多語言這麼做, 尤其 Smalltalk 派其實原 po 的發想完全很合理, 也是已經被充分討論的議題只是和 C 類語言發展的方向不同, 所以感覺在這裡沒溫暖結論是快轉換陣營吧 C-like languages 不是一切 (欸
作者: Killercat (殺人貓™)   2017-10-14 21:55:00
這東西我在Obj-C被婊了無數次,這不是一個好方法...Obj-C你對任何nil(相當於nullptr)的操作都會無聲的過去應該說,這對大多數C/C++ user來講 是很不習慣的事情另外除錯困難等級裡面 pre-compiler < compiler < runtime <<<<<<< silently pass 這剛好屬於最糟的一種
作者: LiloHuang (十年一刻)   2017-10-15 00:41:00
推 Killercat 的見解,沒有 segfault 無聲無息很糟糕..
作者: steve1012 (steve)   2017-10-15 06:47:00
不會報錯的錯是最慘的 幾乎沒好處
作者: y3k (激流を制するは静水)   2017-10-15 11:25:00
這個設計應該有某部分人會需要 感覺也可行 但是對正常人來說B>Z 原因很簡單就是上面說的不會叫的bug最難找 這種設計下去往往只是逼Programer更頻繁的check null或你說的虛無...而且你要知道正常的C/C++ Code規模XD所以如果要做 應該是可以做 但是絕對不會預設為啟用 這很糟

Links booklink

Contact Us: admin [ a t ] ucptt.com