[闲聊] 为什么 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