[討論] 讓programmer控制variable所需的bit數?

看板C_and_CPP (C/C++)作者 (Caesar)時間8年前 (2016/07/30 14:55), 8年前編輯推噓32(364146)
留言186則, 20人參與, 最新討論串1/2 (看更多)
我很好奇,像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) (小弟的觀念可能有錯,這我不太確定) 不知道各位怎麼看這功能? -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 140.114.233.71 ※ 文章網址: https://www.ptt.cc/bbs/C_and_CPP/M.1469861751.A.8E9.html

07/30 15:06, , 1F
不懂,不是已經有bit-field可以指定struct裡面的位元?
07/30 15:06, 1F

07/30 15:06, , 2F
真的需要自訂typedef struct不就好了?
07/30 15:06, 2F
對阿,我知道有bit-field 只是覺得為什麼不要全部的variable都採用bit-field 除此之外,有時候只需要表達一些狀態(例如表達0-31),卻需要用char去存 或是有時候可能只需要21個bit,卻需要用long去存 不覺得這樣很浪費嗎? (而且沒辦法一眼就看出,到底這個variable的range是多少)

07/30 15:07, , 3F
而且這樣搞法如果不能用alignment不是效能更差?
07/30 15:07, 3F
我沒想到alignment的問題... 但是如果原本做不到alignment,換成這種做法,反而有可能做得到不是嗎? 如果仍然做不到,那也會用padding來避免效能更差 所以從alignment方面來看,這麼做應該是不會效能更差吧?

07/30 15:11, , 4F
運算的時候還不是要做bit mask
07/30 15:11, 4F
恩... 所以這樣做的好處可能就不是在效能上,而是在語意的表達上 用這種方式,能更清楚說明,這個variable的值的範圍

07/30 15:49, , 5F
只是要清楚的話 在變數命名上加bit數這樣可以更清楚
07/30 15:49, 5F
可是變數命名不是我能決定的... 如果是用這種方法,那就是強制的了

07/30 16:13, , 6F
對不齊怎麼可能速度更快 噗
07/30 16:13, 6F
會改成這樣,表示新的做法的bit數一定<=現有做法的bit數 那表示說新做法的bit數,一定可以靠padding,來變回現有做法的bit數 那也就是說,現有做法能夠做到的事情(例如alignment),新的做法一定做得到 那這樣alignment所引起的效能問題就不存在了 我的理解是這樣啦

07/30 16:13, , 7F
原因就是不需要 C有那麼多user 對應那麼多硬體
07/30 16:13, 7F

07/30 16:14, , 8F
語言設計出來幾個常用寬度 不同實做可以各自決定
07/30 16:14, 8F
我其實有個問題是 如果未來的硬體實作都改變的話,那怎麼辦? 與其到時候才改標準,不如現在把標準弄得更彈性一點,不是比較好嗎? 反正對於那些主流的硬體,其實沒什麼不同 對於那些特殊的硬體,至少它現在可以說,能支援C語言

07/30 16:15, , 9F
這樣就很_實用_了 就算浪費空間也有限 而且方便互通
07/30 16:15, 9F

07/30 16:16, , 10F
你char寬度7 我寬度6 這種惡夢已經夠久了 不要再來了
07/30 16:16, 10F

07/30 16:19, , 11F
問題應該是CPU處理的效率與空間的利用?
07/30 16:19, 11F

07/30 16:20, , 12F
畢竟CPU指令集對於數字通常都有固定的長度?
07/30 16:20, 12F

07/30 17:18, , 13F
呃我不覺得這個彈性有什麼好處耶…除了複雜化以外XD
07/30 17:18, 13F
大概就是 可以一眼就知道值的範圍 QQ 突然覺得這樣好沒用...

07/30 17:23, , 14F
與其讓使用者決定變數大小 還不如讓編譯器決定
07/30 17:23, 14F

07/30 17:23, , 15F
只要你這語言的語意可以表達得夠清楚(像fp語言)
07/30 17:23, 15F

07/30 17:23, , 16F
很多變數的值的上限都能在編譯期被求出來
07/30 17:23, 16F

07/30 17:23, , 17F
讓使用者不用擔心變數大小 真正的 bit 數編譯器會在編譯
07/30 17:23, 17F

07/30 17:23, , 18F
期幫你決定 你改程式也不用擔心變數大小 編譯器幫你算
07/30 17:23, 18F

07/30 17:23, , 19F
使用上整數就通通是 int 浮點數就全部用 double 之類的…
07/30 17:23, 19F

07/30 17:23, , 20F
至於無法求出上限的就照 C++ 原本標準來做 你覺得這樣如
07/30 17:23, 20F

07/30 17:23, , 21F
07/30 17:23, 21F
如果靠programmer能做得更好的,應該就讓programmer去做 舉例來說,假設我很確定使用者的輸入介於0~7 那我可以宣告 int:3 a; 來存放這個input 可是如果用現有做法,就是 char a; 那這樣programmer在讀我code的時候,前者所能表達的意思比後者更多(如果不用註解) (當然也可以用struct包起來,但大概沒人會願意這麼做) 只用int跟double這方法很不錯(再加一個bool),希望C++能改成這樣 XD

07/30 17:23, , 22F
你說的是抽象化分類的極端 我講的是泛化統整的極端
07/30 17:23, 22F

07/30 17:23, , 23F
這種問題沒有答案 所以…還是照原本就好囉…
07/30 17:23, 23F

07/30 17:23, , 24F
畢竟 C/C++ 都是強調不做太多的語言(像是沒有GC) 這種事
07/30 17:23, 24F
不做太多->programmer要寫比較多code 所以我的提案也蠻符合的吧?

07/30 17:23, , 25F
情需要的人再用 bitfield 就好啦 XD
07/30 17:23, 25F

07/30 17:26, , 26F
整數通通是int,浮點數通通是double←這我喜歡XD
07/30 17:26, 26F

07/30 17:26, , 27F
我除了寫在嵌入式系統斤斤計較以外,通常都只用int...XD
07/30 17:26, 27F

07/30 17:51, , 28F
覺得這樣做會讓可攜性變差.... stdint原本就是為了可攜性
07/30 17:51, 28F

07/30 17:52, , 29F
增加的不用stdint反而各搞各的不是compiler要對應各種需求
07/30 17:52, 29F

07/30 17:52, , 30F
變得更複雜,就是code移到別的平台後效能差很大
07/30 17:52, 30F
還有 121 則推文
還有 28 段內文
08/05 17:12, , 152F
重要吧!
08/05 17:12, 152F

08/12 18:55, , 153F
你cache怎麼放?memory 怎麼放?拿資料一次要拿多少?
08/12 18:55, 153F

08/12 18:55, , 154F
你處理器每次拿資料都要用額外的邏輯去判斷,這個複雜
08/12 18:55, 154F

08/12 18:55, , 155F
度...
08/12 18:55, 155F

08/12 18:58, , 156F
你以為你高階語言想怎麼寫就怎麼寫喔,硬體為了這點沒
08/12 18:58, 156F

08/12 18:58, , 157F
什麼幫助的功能所耗的cost有多大你知道嗎
08/12 18:58, 157F
我覺得我文章寫得一定不好,不然就不會有人提到一些其他方面的問題 我在文章裡面說明了,如果compiler沒辦法提供這功能,那就只要無視它就好 我要的是把bit field的功能,在平常變數宣告時就可以使用,而不用放在struct裡面 如果你們覺得這功能很沒用、一點都不會增進效能、只會增加硬體實作困難 那為什麼C還要提供bit field的功能? 有些人回覆說硬體架構很難做之類的,我可以接受 但是這問題都是早就被解決的,不然bit field早就不存在了

08/17 01:10, , 158F
硬體沒有難不難做...只是要看compiler和硬體要如何合作罷
08/17 01:10, 158F

08/17 01:10, , 159F
了。就算你新增了bit field的語意,要讓它跑在原本的CPU
08/17 01:10, 159F

08/17 01:10, , 160F
也是可以,就只是讓compiler增加原本的工作去support你要
08/17 01:10, 160F

08/17 01:10, , 161F
的語意,用原本的ISA去拼出你想要的functionality,反之
08/17 01:10, 161F

08/17 01:10, , 162F
亦然,可以extend ISA減少compiler的工作。
08/17 01:10, 162F

08/17 01:18, , 163F
不過要讓不同長度的變數pack到同一個register裡,你要讓
08/17 01:18, 163F

08/17 01:18, , 164F
硬體如何對其中一個變數做運算XD。我能想到最接近的概念
08/17 01:18, 164F

08/17 01:18, , 165F
就是SSE了。
08/17 01:18, 165F

08/17 01:23, , 166F
可以參考這http://goo.gl/ahdejN讓你對register packing
08/17 01:23, 166F

08/17 01:23, , 167F
會比較有概念
08/17 01:23, 167F

08/24 08:43, , 168F
那是struct 每一次使用就是會要一整個區塊空間
08/24 08:43, 168F

08/24 08:44, , 169F
就算你變數真的用bit field 也是每次要一個變數的空間
08/24 08:44, 169F

08/24 08:44, , 170F
不會省空間
08/24 08:44, 170F

08/24 08:45, , 171F
struct大太 就是倍數整區塊
08/24 08:45, 171F

08/24 08:46, , 172F
怕你不懂 假設八位元 struct要到的空間就是
08/24 08:46, 172F

08/24 08:47, , 173F
總 bit數/8 取天花板 *8 ok?
08/24 08:47, 173F

08/24 08:48, , 174F
打包一群變數 可以靠命命開頭讓人知道是同群組資料
08/24 08:48, 174F

08/24 08:49, , 175F
struct是連硬體位置都連在一起
08/24 08:49, 175F

08/24 08:51, , 176F
只能說你對c/組合語言/計算機架構完全沒概念
08/24 08:51, 176F

08/24 08:53, , 177F
在你好好念書之前 你永遠都無法理解你的14+2=16bit
08/24 08:53, 177F

08/24 08:53, , 178F
是多外行的說法
08/24 08:53, 178F
有多外行? 從這code來說,http://ideone.com/Y9zcrs A的size是4,B跟C的size是2 用了bit field後,B跟C的size的確小於A 我說用bit field可以省空間,到底哪裡有問題?

08/24 09:04, , 179F
而硬體連續性也是陣列最重要的 因為struct把變數
08/24 09:04, 179F

08/24 09:05, , 180F
的空間連續 陣列才能取用struct裡面的面數
08/24 09:05, 180F

08/24 09:07, , 181F
用命名開頭表示群組 會被compiler打散 效能自然差
08/24 09:07, 181F
int a; //do something int b; //do something int c; 如果每個人都是要用到該變數時才宣告,那這樣子的bit field就沒用 可是,隨便翻一堆code,大部分都是先把會用到的變數宣告在一開始,如下 int a; int b; int c; //do something 那這樣compiler可以嘗試把a b c當作一個struct來包,然後就可以直接套用bit field (這前提當然是,a、b、c可以在struct外面使用bit field) 如果你跟我說,因為上面那原因,導致這想法不夠實際,所以這方法不會被採用 但實際情況不是這樣啊 寫下面那種形式的人比上面多很多 這功能可能很雞肋,但它至少還是有能用的地方的

08/24 09:10, , 182F
比起在這邊跟板友筆戰 不如先好好念底層的原理
08/24 09:10, 182F

08/25 23:11, , 183F
亂入一下,C++ 是建議變數用到時才宣告,所以是建議第一種
08/25 23:11, 183F
我猜會用第二種的原因,應該是很多人從C那邊轉來,所以才寫下面那種方法吧

08/27 08:56, , 184F
對,早期c所有宣告必須放在 Block 最前面
08/27 08:56, 184F

08/27 08:57, , 185F
但新標準已沒差了 (不過寫 FW 還是一樣)
08/27 08:57, 185F

08/27 08:58, , 186F
如果是要省空間的話,看過用 union 來省
08/27 08:58, 186F
話說C++17提供std::variant,來取代union ※ 編輯: Caesar08 (1.164.42.156), 08/27/2016 09:42:03
文章代碼(AID): #1Nd4ztZf (C_and_CPP)
文章代碼(AID): #1Nd4ztZf (C_and_CPP)