[讨论] 让programmer控制variable所需的bit数?

楼主: Caesar08 (Caesar)   2016-07-30 14:55:48
我很好奇,像C跟C++这种那么底层的语言,除了部分variable(bool、float、double)
为何不全部的vairable都用、而且只能用bit-field的方式去宣告?
举例来说
char从C++14开始的定义是至少8 bit
int的定义是至少要16 bit
如果可以改成
int:7 a;
这样表示至少7 bit的int(然后没有char、short、long、long long,统一用int来表示)
所以我能表示的值的范围就从0到127,或是-64到63
如果我要写入这个a值,那我可以写成
a=to_unsigned(60); //存正数
a=to_signed(-30); //存负数
也就是说,a只负责存放资料,它本身不处理正负问题,读跟写都看programmer
func(unsigned int:6 a) //一个存放0到63的a
int *p; //pointer本身大小仍然是32或64 bit,但指向的int就不一定了
int:6 *p; //只能指向至少存放6 bit的int,如果指向int:8也可以
而且对于已经存在的compiler
如果该machine没办法支援这种功能,或是compiler还没做这种功能,那
小于8的就当作8
小于16的就当作16
...
就只是把这功能关掉,其余的跟现在的variable没什么不同
但如果有支援这功能,那就可以更有效地利用bit数
而且cstdint里面的东西大概都不需要了
速度还可能可以提升?
例如现在register是32 bit,我可以读取多个int,只要bit数加总小于或等于32就好
而不会只能读取1或2个int(因为现在int大部分都是32 bit,但其实int指只要求16 bit)
(小弟的观念可能有错,这我不太确定)
不知道各位怎么看这功能?
作者: wtchen (没有存在感的人)   2016-07-30 15:06:00
不懂,不是已经有bit-field可以指定struct里面的位元?真的需要自订typedef struct不就好了?而且这样搞法如果不能用alignment不是效能更差?
作者: CaptainH (Cannon)   2016-07-30 15:11:00
运算的时候还不是要做bit mask
作者: ilikekotomi (Young)   2016-07-30 15:49:00
只是要清楚的话 在变量命名上加bit数这样可以更清楚
作者: MOONRAKER (㊣牛鹤鳗毛人)   2016-07-30 16:13:00
对不齐怎么可能速度更快 噗原因就是不需要 C有那么多user 对应那么多硬件语言设计出来几个常用宽度 不同实做可以各自决定这样就很_实用_了 就算浪费空间也有限 而且方便互通你char宽度7 我宽度6 这种恶梦已经够久了 不要再来了
作者: james732 (好人超)   2016-07-30 16:19:00
问题应该是CPU处理的效率与空间的利用?毕竟CPU指令集对于数字通常都有固定的长度?呃我不觉得这个弹性有什么好处耶…除了复杂化以外XD
作者: CoNsTaR ((const *))   2016-07-30 17:23:00
与其让使用者决定变量大小 还不如让编译器决定只要你这语言的语意可以表达得够清楚(像fp语言)很多变量的值的上限都能在编译期被求出来让使用者不用担心变量大小 真正的 bit 数编译器会在编译期帮你决定 你改程式也不用担心变量大小 编译器帮你算使用上整数就通通是 int 浮点数就全部用 double 之类的…至于无法求出上限的就照 C++ 原本标准来做 你觉得这样如何你说的是抽象化分类的极端 我讲的是泛化统整的极端这种问题没有答案 所以…还是照原本就好囉…毕竟 C/C++ 都是强调不做太多的语言(像是没有GC) 这种事情需要的人再用 bitfield 就好啦 XD
作者: james732 (好人超)   2016-07-30 17:26:00
整数通通是int,浮点数通通是double←这我喜欢XD我除了写在嵌入式系统斤斤计较以外,通常都只用int...XD
作者: wtchen (没有存在感的人)   2016-07-30 17:51:00
觉得这样做会让可携性变差.... stdint原本就是为了可携性增加的不用stdint反而各搞各的不是compiler要对应各种需求变得更复杂,就是code移到别的平台后效能差很大
作者: CoNsTaR ((const *))   2016-07-30 17:58:00
使用者输入就是一个编译器算不出上/下限的东西啊 这种东西照你的方法是很适合没错啦XD应该说是各有用途 用在不同地方吧或许你已经强制指定的编译器就直接用你的特化版没指定的它再帮你算 你没指定它又算不出来看是要报错 还是用原本标准这样写个程式也好累喔 XDDD 不过是满不错的构想啦说真的增加程式安全性
作者: wtchen (没有存在感的人)   2016-07-30 18:04:00
是觉得这种大部份新手不会用的功能不要加进去真的必要用bit-field就好,否则debug起来又是灾难
作者: CoNsTaR ((const *))   2016-07-30 18:07:00
debug 灾难没错 不过这做法也可以避免掉很多很多 bug 了XD
作者: Sidney0503 (Sidney0503)   2016-07-30 18:28:00
你都说底层了 你知道c和组语的关系吗........另外 C++已经可以说跟C截然不同了首先你的目的是什么? 你想要控制值的范围?那就是一件很奇怪的事 因为都是2^n相关你想要跑快一点 只要一次pipeline可以吃 几bit都没差省空间? 与其省这个不如code写好一点基本上C往下挖就是组合语言 组合语言往下挖就是CPU硬件架构会基于软件 软件会被硬件牵制就算有你所谓的"未来架构" 那也会有"未来指令"有"编译器"的理论在 就会有对应的语言
作者: wtchen (没有存在感的人)   2016-07-30 19:22:00
在使用bit-field的时候endianness也要考虑进去
作者: netsphere (Ruby&Waku)   2016-07-30 19:22:00
type-safty表示
作者: wtchen (没有存在感的人)   2016-07-30 19:23:00
(就可携性来说,使用bit-field已经有点危险了)全部type都变成bit-field,考虑到endianness结果有点可怕
作者: descent (“雄辩是银,沉默是金”)   2016-07-30 21:51:00
我现在会用 type unsigned int u32, 然后用 u32不想直接用 unsigned int 这样的用法了最近踩一堆雷
作者: LiloHuang (十年一刻)   2016-07-30 22:49:00
楼上改用 stdint.h 的 uint32_t 呢
作者: descent (“雄辩是银,沉默是金”)   2016-07-30 22:54:00
字太多, 打起来累人, u32, u8, u16, 你打一个我打3个
作者: LiloHuang (十年一刻)   2016-07-30 23:01:00
个人觉得 C99 标准能用则用,打字累人则是另一回事了XD
作者: wtchen (没有存在感的人)   2016-07-30 23:11:00
为啥不typedef uint32_t u32,这样不是安全些?
作者: yvb   2016-07-30 23:23:00
int 7:xxx; ==> union { int yyy:7 } xxx;然后再 #define xxx xxx.yyy接着 xxx = 127; ==> ok; xxx = 128; ==> warning当然若考虑 define 可能会有额外风险, 就直接用 xxx.yyy .
作者: CoNsTaR ((const *))   2016-07-30 23:29:00
可是楼上 xxx = func(); 默认是不会 warning 的 就算 func 回传常数 128 也一样
作者: yvb   2016-07-30 23:30:00
当然 , struct { int yyy:7 } xxx; 一样效果.语法本身不提供 int:7 写法, 转个弯换写法效果一样.当然, 其中的 int yyy:7 和 long long yyy:7 应该会相同;但写 char yyy:7 或 short yyy:7 会不同(前提用 32 bit 机器)上两句可能和机器及编译器,甚至编译选项相关, 请忽略.回 CoNsTaR: 只是验证是有 int:7 效果, 设128去印应该会是0.
作者: kevingwn (如云如风的人生)   2016-07-30 23:52:00
省空间是说想要vector<int6_t>这样的操作吗?应该是办得到,但效能应该比vector<int8_t>差很多通常只有在存成档案或网络传输等会有这样的需求吧?
作者: TobyH4cker (Toby (我要当好人))   2016-07-31 00:02:00
看来没写过组语哦,看懂了,不过我觉得指明跟不指明没差,因为本来就是要看文件,把文件的规范读的很精熟的话,coding起来比较容易至于你说那些新手,或是老手都还不知道实际大小那些,只是表面他们学得不够或看得不够而已但是你的想法其实可以带来一个好处,就是整数型态就只要有int跟uint就够了,手动指定最小bit数,compiler来安排它要用多大空间这样,吧?嗯嗯那signed跟unsigned你会怎么做0.0
作者: wtchen (没有存在感的人)   2016-07-31 16:20:00
还有一个问题,怎么判断是否overflow?这样搞的话要弄一个header把所有可能的max/min define进去
作者: CoNsTaR ((const *))   2016-07-31 17:05:00
楼上这么做的优点就是不用考虑 overflow 啊…你已经知道它在这个程式里有可能被赋的最大最小值了 怎么会 overflow我也认同原 po sint int uint 的构想只是我觉得 signed unsigned (原本是 modifier) 可以变成像是 const 那样的东西(qualifier)int (specifier) 本身可以储存任何整数 但是一旦加了 signed/unsigned你就不能赋 正/负 数给他就像加 const 一样,你就不能赋 non-const 给他这么做 int 的本质不会改变 但是编译器会为你做额外的检查,保证你没有把不对的值赋给变量这样的好处是,这三种型态实际上是一模一样的,只是你给他们一些限制所以 int 装得下的数字其他两种一定也装得下(不会 overflow,cast 的时候 binary 值也不会改变)至于 casting 规则嘛……
作者: wtchen (没有存在感的人)   2016-07-31 18:17:00
原创的使用者可以自订范围,只是如果多人一起编辑恐怕会加深code的复杂度....
作者: CoNsTaR ((const *))   2016-07-31 18:20:00
w大 不太懂你的问题耶…
作者: wtchen (没有存在感的人)   2016-07-31 18:29:00
<= 16 bit好解决,如果是> 16 bit 那还要记不同bit的最大最小值? (我算术不好不能一眼看出来)除非一直用2进位或16进位,如果要转到10进位就....至于bit field vs. endianness 可以看这里:http://mjfrazer.org/mjfrazer/bitfields/
作者: CoNsTaR ((const *))   2016-07-31 19:01:00
喔喔 其实没有那么复杂啊 因为只有某些特殊值的上下限是需要你手动定义的 像是 协定里某个值的上下限/输入输出能接受的上下限 之类 剩下的其实都可以在编译时期动态的决定
作者: kevingwn (如云如风的人生)   2016-07-31 21:26:00
用struct去包不会麻烦呀 http://ideone.com/EF6eUs倒是觉得vector<int4_t>比较困难
作者: Sidney0503 (Sidney0503)   2016-07-31 21:58:00
说真的我不懂你的需求光你说摆再一起省空间 很想叫你去念计算机组织首先 管bit不是在管硬盘block 光是纪录就要消耗多少多少空间 其次先不谈对齐问题你要如何设计一个CPU可以同时执行两个指令?pipeline一次就是吃这么多bit 你空下来又如何?我觉得你拿去八卦版问比较好 人比较多 也不只C说不定精通其他语言的人会帮你解答
作者: CoNsTaR ((const *))   2016-07-31 22:36:00
楼上重点错误吧……
作者: yoco (眠月)   2016-07-31 22:39:00
我觉得不是不行,只是没有人写 proposal 给标准委员会你写一份吧就像 C++11 没有 VAL,不是不行,单纯只是没人提 proposal
作者: wtchen (没有存在感的人)   2016-07-31 22:52:00
Sidney0503讲的是Write amplification吗?
作者: Sidney0503 (Sidney0503)   2016-08-01 06:48:00
楼上说的是我其中一个想法 我真的想不到如何省空间..你现在又跟我说表示值的范围 我最一开始就说很奇怪为什么值的范围只能是2^n次方 根本就不符合使用除了bool 大多数我们使用的数字范围都不是2^n天堂32767和战神65535一看就知道是被硬件牵制而不是使用需求才设这个范围这种边界的问题生出物件的原则像JAVA惯用set和get原来你知道什么叫硬件不好设计阿 我还以为你不知道耶我已经跟你说了就是惯用的set和get会限制边界难不成我用你的API还要看每个变量的范围?
作者: wtchen (没有存在感的人)   2016-08-01 17:21:00
以后量子电脑如果成功量产,1 bit 就能表示成0~7搞不好C standard也要全部重新定义
作者: chchwy (mat)   2016-08-01 18:11:00
就CPU的角度来说 你的建议完全不会增加效能
作者: goliathplus (No Comment)   2016-08-05 00:02:00
因为没有意义阿 硬件架构要 ALIGN 单一变量指定bit没有显著优点阿
作者: tomjpsun (汤姆熊)   2016-08-05 17:09:00
RAM 越来越大碗,连 embedded system 也有受惠, 所以十年前是应该考虑这些,但是现在其实容易 maintain 可能比较重要吧!
作者: jeff04209 (yo)   2016-08-12 18:55:00
你cache怎么放?memory 怎么放?拿资料一次要拿多少?你处理器每次拿资料都要用额外的逻辑去判断,这个复杂度...你以为你高阶语言想怎么写就怎么写喔,硬件为了这点没什么帮助的功能所耗的cost有多大你知道吗
作者: jun0325 (俊)   2016-08-17 01:10:00
硬件没有难不难做...只是要看compiler和硬件要如何合作罢了。就算你新增了bit field的语意,要让它跑在原本的CPU也是可以,就只是让compiler增加原本的工作去support你要的语意,用原本的ISA去拼出你想要的functionality,反之亦然,可以extend ISA减少compiler的工作。不过要让不同长度的变量pack到同一个register里,你要让硬件如何对其中一个变量做运算XD。我能想到最接近的概念就是SSE了。可以参考这http://goo.gl/ahdejN让你对register packing会比较有概念
作者: Sidney0503 (Sidney0503)   2016-08-24 08:43:00
那是struct 每一次使用就是会要一整个区块空间就算你变量真的用bit field 也是每次要一个变量的空间不会省空间struct大太 就是倍数整区块怕你不懂 假设八位元 struct要到的空间就是总 bit数/8 取天花板 *8 ok?打包一群变量 可以靠命命开头让人知道是同群组资料struct是连硬件位置都连在一起只能说你对c/组合语言/计算机架构完全没概念在你好好念书之前 你永远都无法理解你的14+2=16bit是多外行的说法而硬件连续性也是阵列最重要的 因为struct把变量的空间连续 阵列才能取用struct里面的面数用命名开头表示群组 会被compiler打散 效能自然差比起在这边跟板友笔战 不如先好好念底层的原理
作者: EdisonX (卡卡兽)   2016-08-25 23:11:00
乱入一下,C++ 是建议变量用到时才宣告,所以是建议第一种

Links booklink

Contact Us: admin [ a t ] ucptt.com