討論區快速選單
知識庫快速選單
掌握Salesforce雲端管理秘訣 網路投保旅行平安險 程式設計俱樂部Facebook粉絲團
[ 回上頁 ] [ 討論區發言規則 ]
為什麼有人常用 unsigned char 來宣告字串?
更改我的閱讀文章字型大小
作者 : ice_emissary(燃燒的大地) 貼文超過200則
[ 貼文 408 | 人氣 0 | 評價 1890 | 評價/貼文 4.63 | 送出評價 18 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2016/5/30 下午 05:33:15
在說明我的疑問前,先交代一下這個疑問的由來。

我在工作上常需要接觸,或修改前人的程式,這些程式通常都有一定的年歲。
這些程式裡會把字串類型的變數宣告成 unsigned char,例如:

unsigned char *str1;
unsigned char *str2[32];

甚至是參數的傳遞也是:

unsigned char* str_func(unsigned char *str);

程式裡面通篇是這樣的寫法,因為這和 C 語言預設的字串型態不一樣,所以用起來會遇到一大堆關於型態不相符的警告,
為了解決這些警告,於是程式裡通篇可以見到這樣的寫法:

fopen((char*)"filename", "r");
unsigned char* strres = str_func((unsigned char*)"Hello");

用起來很麻煩,除了強制轉型會讓很多時候真正的型態衝突被隱藏起來之外,還讓敘述變很長,寫起來累。
甚至很多地方的字串拷貝乾脆就不用 strcpy 而使用 memcpy。
更精彩的是,可能有位前輩為了一次解決當時的問題,竟然還宣告了巨集:

#define strlen(str) strlen((char*)str)
#define strcmp(str1,str2) strcmp((char*)str1, (char*)str2)

這些精彩的表現看得我只能說是嘆為觀止!
起初在第一份程式見到 unsigned char 的寫法時,覺得當初寫這程式的人一定是個白痴,
因為我覺得這種寫法沒有優點,只有給自己找麻煩而已;
但後來接二連三看到,只要是老案子幾乎都是這樣的寫法,甚至不同公司的程式碼也是。
於是我在想這種使用 unsigned char 而不用 char 的寫法是不是有什麼歷史的由來或典故,
想請版上知道這些事情的老前輩能說點故事,以解我心中之疑惑。

感謝大家!
作者 : kagaya(kagaya) VC++優秀好手C++優秀好手貼文超過1000則人氣指數超過30000點
[ 貼文 1602 | 人氣 38709 | 評價 4610 | 評價/貼文 2.88 | 送出評價 115 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
主題發起人ice_emissary註記此篇回應為很有道理 2016/5/30 下午 06:35:29
char 是 -128~127
unsigned char 是 0~255
而extend ascii 是 0~255
所以存字串用 unsigned char我覺得不奇怪呀

作者 : ozzy123(ozzy) VC++優秀好手資訊類作業求救卓越專家C++卓越專家貼文超過4000則人氣指數超過30000點
[ 貼文 4499 | 人氣 37262 | 評價 11100 | 評價/貼文 2.47 | 送出評價 49 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2016/5/30 下午 09:05:11
memcpy is safer than strcpy
作者 : chiuinan2(青衫)討論區板主 Visual C++ .NET卓越專家VC++一代宗師Visual Basic優秀好手資訊類作業求救卓越專家一般曠世奇才程式設計甘苦談優秀好手C++ Builder優秀好手上班族的哈拉園地優秀好手C++頂尖高手Assembly優秀好手貼文超過3000則人氣指數超過150000點
[ 貼文 3732 | 人氣 170106 | 評價 34520 | 評價/貼文 9.25 | 送出評價 125 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
主題發起人ice_emissary註記此篇回應為很有道理 2016/5/30 下午 11:14:01
會用unsigned char的時機主要有兩種,一種是要用一個byte存數值0-255,不想有負數。例如絕大部份的加密或編碼運算,像是MD5、SHA-256、CRC32等等,內部都是使用unsigned char*。另一種便是處理非英數字元,例如BIG-5中文字串(這個機率比較大)。例如:

const char* s = "一"; // 換成數值就是0xA4, 0x40 //
if (s[0] == 0xA4) { ... };

看似正確,其實這樣的寫法,條件將會永遠不成立(但會有一個有號數與無號數混用的警告訊息)。因s[0]是有號數,所以0xA0會被看成負數,以32位元無號數值來看,便是0xFFFFFFA4,跟0x000000A4是不會相等的。有經驗的programmer會記得在前面加個unsigned char來避免此一問題:

if ((unsigned char)s[0] == 0xA4) { ... };

但不是每個programmer都那麼細心。於是將字串宣告成unsigned char*,便可以避免此一誤用情況。好壞難講,但一般是利大於弊。若是處理純英數字串,便沒必要宣告成unsigned char*了。

作者 : sflam(Raymond)討論區板主 Visual C++ .NET卓越專家VC++一代宗師新手入門優秀好手資訊類作業求救頂尖高手C++一代宗師貼文超過4000則
[ 貼文 4945 | 人氣 9172 | 評價 32290 | 評價/貼文 6.53 | 送出評價 142 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
主題發起人ice_emissary註記此篇回應為很有道理 2016/5/30 下午 11:44:17
>char 是 -128~127

不完全正確. 在 C 及 C++ 語言裡, char, signed char, 及 unsigned char 是三個不同的類型. 這有別於其它整數類型.

C++ 3.9.1 Fundamental types 第一段:

"... Characters can be explicitly declared unsigned or signed. Plain char, signed char, and unsigned char are three distinct types."

"... In any particular implementation, a plain char object can take on either the same values as a signed char or an unsigned char; which one is implementation-defined."

所以 'char' 的範圍可以是 signed char 的範圍, 也可以是 unsigned char 的範圍. 這也是頭檔 <limits.h> 內有CHAR_MIN, CHAR_MAX, SCHAR_MIN, SCHAR_MAX, 及 UCHAR_MAX 等定義的原因. 程式員也可以用這些定義來判斷個別編譯器裡 char 的取值範圍.

至於樓主所說的程式, 也許要看當時的編譯器及對象平台是否導致了這個需要. 有時候也許是最底下的某一個用法的需要, 影響了上層呼叫這個底層函式的寫法, 然後一層層的影響上去. 當然也不排除當時程式員的程度問題.

作者 : ice_emissary(燃燒的大地) 貼文超過200則
[ 貼文 408 | 人氣 0 | 評價 1890 | 評價/貼文 4.63 | 送出評價 18 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2016/6/1 上午 07:41:05
謝謝大家的回答,
所以整理一下會使用 unsigned char 的有益理由,通常是因為需要做加解密等變換處理、或非傳統 ASCII 字元處理的關係吧!

老實說我一開始以為這是類似像 const 這種在 K&R C 時代因為語法因素所造成的,但現在看起來好像是因為方便某種特定資料處理的關係。
如果是這樣的話,我覺得應該要在某一個適當的層裡為字串做轉型,使得只有在需要的某些底層才用 unsigned char 處理字串;
而不是讓 unsigned char 無限的擴散到所有地方,給大部分的一般使用帶來不便。
尤其是還有一家公司發給我們的 API 裡的字串參數竟然也是 unsigned char,都已經到頂層介面層了耶!

至於 signedunsigned 的議題,我之前好像有看過,C 語言中除了 char 以外的所有整數都隱含為 signed 的,只有 char 比較特別。
char 若未加上符號修飾則其可能為 signedunsigned,由編譯器決定。
我以前使用 C++ Builder 6 的時候記得還有這麼一個編譯選項是用來選擇要編譯器將 char 隱含為有號還是無號呢!
作者 : ozzy123(ozzy) VC++優秀好手資訊類作業求救卓越專家C++卓越專家貼文超過4000則人氣指數超過30000點
[ 貼文 4499 | 人氣 37262 | 評價 11100 | 評價/貼文 2.47 | 送出評價 49 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2016/6/1 下午 03:42:20
this is regardless of encryption and crypt-ion .
作者 : sunyear(coco) VC++卓越專家C++頂尖高手貼文超過2000則
[ 貼文 2421 | 人氣 1485 | 評價 6060 | 評價/貼文 2.5 | 送出評價 5 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2016/6/2 上午 11:40:21
>所以整理一下會使用 unsigned char 的有益理由,通常是因為需要做加解密等變換處理、或非傳統 ASCII 字元處理的關係吧!
很多 8 bits CPU本身運算signed型態的能力很弱。用unsigned char型態效率高也節省程式碼。
作者 : cxxlman(CxxlMan) C++優秀好手貼文超過1000則
[ 貼文 1042 | 人氣 3227 | 評價 1260 | 評價/貼文 1.21 | 送出評價 28 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2016/6/3 下午 12:25:48

>>所以整理一下會使用 unsigned char 的有益理由,通常是因為需要做加解密等變換處理、或非傳統 ASCII 字元處理的關係吧!
>很多 8 bits CPU本身運算signed型態的能力很弱。用unsigned char型態效率高也節省程式碼。

請問現在對於一般形別(char int short long) 佔用記憶體空間的定義是怎樣
作者 : ice_emissary(燃燒的大地) 貼文超過200則
[ 貼文 408 | 人氣 0 | 評價 1890 | 評價/貼文 4.63 | 送出評價 18 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2016/6/3 下午 01:25:19
我想 coco 大的意思是有些 CPU 沒有特別為有號數的計算做足夠的優化,所以在沒有負號問題的計算上,把型態定義為無號整數會算比較快。
當然,也有另一批 CPU 情況相反,使其有號數會算得比無號數快。
我記得曾經有文章在討論這件事情。

但這些都是與計算效率有關的議題,和變數佔用記憶體空間的議題無關喔!
對於一般型別佔用空間的定義,C 語言應該從來沒有對其做過改變;
如果你要問的是像 int 應該佔用確切多少個個位元組這樣的問題的話,答案是不固定,其由系統平臺決定。
作者 : ozzy123(ozzy) VC++優秀好手資訊類作業求救卓越專家C++卓越專家貼文超過4000則人氣指數超過30000點
[ 貼文 4499 | 人氣 37262 | 評價 11100 | 評價/貼文 2.47 | 送出評價 49 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2016/6/3 下午 02:09:24
https://msdn.microsoft.com/en-us/library/s3f49ktz.aspx
https://www.macs.hw.ac.uk/~pjbk/pathways/cpp2/node7.html
https://developer.mbed.org/handbook/C-Data-Types
http://stackoverflow.com/questions/7180196/size-of-integer-in-c
作者 : cxxlman(CxxlMan) C++優秀好手貼文超過1000則
[ 貼文 1042 | 人氣 3227 | 評價 1260 | 評價/貼文 1.21 | 送出評價 28 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2016/6/3 下午 03:05:41

>對於一般型別佔用空間的定義,C 語言應該從來沒有對其做過改變;
>如果你要問的是像 int 應該佔用確切多少個個位元組這樣的問題的話,答案是不固定,其由系統平臺決定。

確定還是不固定嗎?有沒有比較肯定的資料來源,理由是網路時代,系統平臺決定不同大小很難不出槌
作者 : ozzy123(ozzy) VC++優秀好手資訊類作業求救卓越專家C++卓越專家貼文超過4000則人氣指數超過30000點
[ 貼文 4499 | 人氣 37262 | 評價 11100 | 評價/貼文 2.47 | 送出評價 49 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2016/6/3 下午 03:24:16
https://msdn.microsoft.com/en-us/library/296az74e.aspx
native file depends on specific platform. it is a nature issue of compiler.
作者 : ice_emissary(燃燒的大地) 貼文超過200則
[ 貼文 408 | 人氣 0 | 評價 1890 | 評價/貼文 4.63 | 送出評價 18 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2016/6/3 下午 03:40:00
> 確定還是不固定嗎?

是的。

> 有沒有比較肯定的資料來源,

沒有,也許有其他人可以提供,因為我己經忘了從哪看來的了!

> 理由是網路時代,系統平臺決定不同大小很難不出槌

如果你需要使用固定大小的變數,請改用像是 uint32_t、int64_t 的延伸型態,定義在 stdint.h 裡,是從 C99 加入的。
作者 : ice_emissary(燃燒的大地) 貼文超過200則
[ 貼文 408 | 人氣 0 | 評價 1890 | 評價/貼文 4.63 | 送出評價 18 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2016/6/3 下午 03:41:11
http://www.cplusplus.com/reference/cstdint/
作者 : ozzy123(ozzy) VC++優秀好手資訊類作業求救卓越專家C++卓越專家貼文超過4000則人氣指數超過30000點
[ 貼文 4499 | 人氣 37262 | 評價 11100 | 評價/貼文 2.47 | 送出評價 49 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2016/6/3 下午 03:45:38
https://en.wikipedia.org/wiki/C_data_types
.... "The actual size of integer types varies by implementation. The standard only requires size relations between the data types and minimum sizes for each data type:"
....
cite above site
作者 : cxxlman(CxxlMan) C++優秀好手貼文超過1000則
[ 貼文 1042 | 人氣 3227 | 評價 1260 | 評價/貼文 1.21 | 送出評價 28 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2016/6/3 下午 05:29:53

>> 確定還是不固定嗎?
>
>是的。
>
>> 有沒有比較肯定的資料來源,
>
>沒有,也許有其他人可以提供,因為我己經忘了從哪看來的了!
>
>> 理由是網路時代,系統平臺決定不同大小很難不出槌
>
>如果你需要使用固定大小的變數,請改用像是 uint32_t、int64_t 的延伸型態,定義在 stdint.h 裡,是從 C99 加入的。

為了因應網路時代,是不是應該放棄 int long ... 等不固定大小的形別,若不須放棄理由是什麼
作者 : ice_emissary(燃燒的大地) 貼文超過200則
[ 貼文 408 | 人氣 0 | 評價 1890 | 評價/貼文 4.63 | 送出評價 18 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2016/6/4 上午 12:08:37
> 為了因應網路時代,是不是應該放棄 int long ... 等不固定大小的形別,若不須放棄理由是什麼

當然不該放棄,即使是網路時代,寫程式也不會只有網路程式可以寫;甚至即使是網路程式,也不是只有資料交換。很多時候我們還有一般用途的計算。

舉例來說,當我要做一些數字的計算時,我其實不是很在乎數字的型態到底佔用多少位元組,只要不是小到會溢出就好了。
但是不同平臺上效率最佳的數值長度往往不盡相同,比如說 A 平臺運算最快的是 16 位元整數、B 平臺運算最快的是 32 位元整數、C 平臺運算最快的是 8 位元整數,那我的程式碼拿到不同的平臺上編譯執行前就要不厭其煩的修改我所有的變數型態定義,以符合當地平臺最適當的尺寸。

因此有一種偉大的類型被發明出來,即為不定長變數,這種變數在不同平臺上的尺寸不定相同。因此我的程式碼可以使用這種型態來定義變數,而不需要隨者執行平臺一改再改,因為編譯器會幫我做這件事。亦即,整數變數在 A 平臺上可能為 16 位元長、在 B 平臺上為 32 位元、到了 C 平臺又變成 8 位元。總之,我不需要再好精神拘暱於到底要選用多大的變數上。

C 語言的基本變數定義就是建立在這樣的關係上產生出來的,當我要一個普通的整數時就宣告 int;當我算的東西數字可能會大一點,怕會溢出,就宣告長一點的 long;當我算的數字很小,希望省點空間時可以使用短一點的 short。這樣整個變數型態都是建立在相對的大小上,其實際的長度必須在編譯時才會知道,事實上大部份時候我們應該也不需要在意它到底佔多少空間。

類似的現象還出現在資料結構上面,不同的對齊模式會導致同一個資料結構最終的大小不相同。

總之,固定長和不定長的型態各有優缺,各有適合的應用。在網路資料或檔案資料交換的場合,固定長變數能避免像不定長變數帶來的資料錯亂問題;但在計算場合上,使用固定長變數卻可能無法發回平臺上的最佳計算效能。
作者 : sunyear(coco) VC++卓越專家C++頂尖高手貼文超過2000則
[ 貼文 2421 | 人氣 1485 | 評價 6060 | 評價/貼文 2.5 | 送出評價 5 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2016/6/4 上午 01:01:27
>請問現在對於一般形別(char int short long) 佔用記憶體空間的定義是怎樣
這種定義不會改變的,改變了相容性就崩潰了!
為什麼當初對這些形別的寬度不固定?
因為有些CPU運算資料寬度不一定。
我說的並不是如同x86的8位元,16位元,32位元或64位的不同。
x86不論是幾位元,都還是一個地址的資料對應一個8位元。
但有些CPU,例如TI的DSP有16位元,32位元。它們是一個地址對應一個16bits或32bits資料。
(舉個例子,地址0000存放0x1234,而地址0001則存放0x5678)
如果C/C++固定了形別寬度,對這些CPU麻煩就大了!

對於不同系統交換資訊,確定的資料寬度是有其必要沒有錯。但這很容易經由macro定義來解決。
作者 : ozzy123(ozzy) VC++優秀好手資訊類作業求救卓越專家C++卓越專家貼文超過4000則人氣指數超過30000點
[ 貼文 4499 | 人氣 37262 | 評價 11100 | 評價/貼文 2.47 | 送出評價 49 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2016/6/4 上午 09:25:37
ANSI c didn't strictly define size of elementary data type.
作者 : sflam(Raymond)討論區板主 Visual C++ .NET卓越專家VC++一代宗師新手入門優秀好手資訊類作業求救頂尖高手C++一代宗師貼文超過4000則
[ 貼文 4945 | 人氣 9172 | 評價 32290 | 評價/貼文 6.53 | 送出評價 142 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2016/6/4 上午 11:29:33
>請問現在對於一般形別(char int short long) 佔用記憶體空間的定義是怎樣

語言標準沒有定義, 因為各系統平台架構不同, 也不可能定義.

雖然如此, 但作為程式語言, 它還是有一些規範及最低要求的, 比方說:

- 各整數類型的容量關係是:
   signed char <= short <= int <= long <= long long
   float <= double <= long double
  也就是說, 左邊的類型是右邊的 subset.

- signed 類型的正值必須是同類型 unsigned 的 subrange.
 比方說, unsigned int 的範圍必須包括 int 的正數值的範圍.

- sizeof(char) == 1.
  
- char 必須能夠儲存基本字集 (character set), 而且不能是負值.
 所以, 這表示 char 必須至少是 7 個位元 (0~127. 7 value-bits). 但標準文件裡的附註部份 Implementation Limits 有規定 CHAR_BIT 至少是 8.

- 規定各類型 *_MIN/*_MAX 的絕對值, 不能小於某範圍, 比方說:
  SCHAR_MIN/MAX : -127/+127
  UCHAR_MAX : 255
  SHRT_MIN/MAX : -32767/+32767
  USHRT_MAX : 65535
  INT_MIN/MAX : -32767/+32767
  UINT_MAX : 65535
  LONG_MIN/MAX : -2147483647/+2147483647
  ULONG_MAX : 4294967295
作者 : ozzy123(ozzy) VC++優秀好手資訊類作業求救卓越專家C++卓越專家貼文超過4000則人氣指數超過30000點
[ 貼文 4499 | 人氣 37262 | 評價 11100 | 評價/貼文 2.47 | 送出評價 49 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2016/6/4 上午 11:39:50
http://stackoverflow.com/questions/8010040/why-is-schar-min-defined-as-127-in-c99
http://tigcc.ticalc.org/doc/limits.html
作者 : cxxlman(CxxlMan) C++優秀好手貼文超過1000則
[ 貼文 1042 | 人氣 3227 | 評價 1260 | 評價/貼文 1.21 | 送出評價 28 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2016/6/4 下午 12:29:01

>對於不同系統交換資訊,確定的資料寬度是有其必要沒有錯。但這很容易經由macro定義來解決。

你是說用 macro 固定形別大小,放棄不固定大小的一般形別是嗎?
這樣我就搞不清楚你立場是支持還是反對
作者 : cxxlman(CxxlMan) C++優秀好手貼文超過1000則
[ 貼文 1042 | 人氣 3227 | 評價 1260 | 評價/貼文 1.21 | 送出評價 28 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2016/6/4 下午 04:37:20

>http://stackoverflow.com/questions/8010040/why-is-schar-min-defined-as-127-in-c99
>http://tigcc.ticalc.org/doc/limits.html
>

 ozzy123 你給的資料都是固定大小,是標準還是只限某個平台而已
作者 : ozzy123(ozzy) VC++優秀好手資訊類作業求救卓越專家C++卓越專家貼文超過4000則人氣指數超過30000點
[ 貼文 4499 | 人氣 37262 | 評價 11100 | 評價/貼文 2.47 | 送出評價 49 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2016/6/4 下午 04:52:04
so this is answer
作者 : cxxlman(CxxlMan) C++優秀好手貼文超過1000則
[ 貼文 1042 | 人氣 3227 | 評價 1260 | 評價/貼文 1.21 | 送出評價 28 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2016/6/5 上午 10:33:44
因 c++ 的形別大小不固定,所以若要用在跨平台,且彼此間資料也會交換,一般的做法應該用中繼檔的方法,即把一般形別資料轉換成中繼資料,這中繼資料拿到另一平台,再轉換(還原)成原來形別的資料,那麼就可以不在乎形別在各平台大小的不同了
作者 : cxxlman(CxxlMan) C++優秀好手貼文超過1000則
[ 貼文 1042 | 人氣 3227 | 評價 1260 | 評價/貼文 1.21 | 送出評價 28 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2016/6/5 下午 09:01:20

>- 規定各類型 *_MIN/*_MAX 的絕對值, 不能小於某範圍, 比方說:
>  SCHAR_MIN/MAX : -127/+127
>  UCHAR_MAX : 255
>  SHRT_MIN/MAX : -32767/+32767
>  USHRT_MAX : 65535
>  INT_MIN/MAX : -32767/+32767
>  UINT_MAX : 65535
>  LONG_MIN/MAX : -2147483647/+2147483647
>  ULONG_MAX : 4294967295

對於溢位的處理,就用R大提供的最小範圍定義作為最大範圍過濾檢查
作者 : sunyear(coco) VC++卓越專家C++頂尖高手貼文超過2000則
[ 貼文 2421 | 人氣 1485 | 評價 6060 | 評價/貼文 2.5 | 送出評價 5 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2016/6/5 下午 09:04:34
>>對於不同系統交換資訊,確定的資料寬度是有其必要沒有錯。但這很容易經由macro定義來解決。
>你是說用 macro 固定形別大小,放棄不固定大小的一般形別是嗎?
有有說放棄嗎?
我說,char,int...若固定大小,除了相容性問題外。也會在某些CPU上造成運算效率上很大的困擾。
例如TMS 320C25的資料是16 bits,如果把char定義成8 bits的固定寬度。
那麼
char a,b;
編譯器把 a分配在 (地址)0x1200的bit0~bit7;b分配在(地址)0x1200的bit8~bit15
請問 &a或&b該給你怎麼樣的地址?
我說可以用macro固定大小,不是要放棄原來的型別(上面的例子,已明白顯示不能放棄)。
而是跨裝置資料交換,明確的資料寬度有其需要。
但這種需要整個程式是局部性的,可以使用macro解決

>ozzy123 你給的資料都是固定大小,是標準還是只限某個平台而已
那是一些讓程式可以取得所用平台/編譯器一些型別最大值,最小值等資料的macro。
正如我說的,(局部)需要固定寬度的型別(或大小)本來就可以使用macro來達到。
(特別加了局部,免得你又誤解要全盤放棄原來不固定的定義)
作者 : cxxlman(CxxlMan) C++優秀好手貼文超過1000則
[ 貼文 1042 | 人氣 3227 | 評價 1260 | 評價/貼文 1.21 | 送出評價 28 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2016/6/6 上午 10:46:27
我的意思是你提出了 macro 就是等於 "放棄使用" 不固定大小的一般形別,用 macro "替代"

至於是否要把一般形別真正從 C++ 拿掉,我想會有很大的爭議,但我覺得也無妨,不是
有 uint32_t 這樣的東西嗎,若要用 macro 得自己為各平台寫 macro,還不如用 uint32_t

對於 CPU 硬體上的適用性,就留給編譯器去傷腦筋

還有另一種選擇是用大數,形別會有這種多麻煩是因同樣是整數卻有很多種,若用大數就簡單多了,不管
怎樣去實作它,只要中繼資料格式統一就行了

就剩 效率與實用 之間的選擇了,若你希望你寫的程式碼能有明天,你會選擇哪一邊
作者 : ice_emissary(燃燒的大地) 貼文超過200則
[ 貼文 408 | 人氣 0 | 評價 1890 | 評價/貼文 4.63 | 送出評價 18 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2016/6/6 下午 01:03:34
> 對於 CPU 硬體上的適用性,就留給編譯器去傷腦筋

所以編譯器的解決方法就是提供一組不定長的型別。

> 還有另一種選擇是用大數…

沒錯,但是大數的效率可是更差的!
你用過 Matlab 嗎?你可以試著用它來解算流場,就會知道什麼叫作效率差了!

> 就剩 效率與實用 之間的選擇了,若你希望你寫的程式碼能有明天,你會選擇哪一邊

就是為了寫程式能夠有明天,所以我不會偏向任何一方。
因其各有所長、各有所短;各有所用、也各有所非用。
你能把全臺灣的車子都統一成小客貨兩用車嗎?沒有小客車、沒有大貨車、沒有連結車、也沒有大客車,就只允許有一種通用的小客貨車在路上行使。
那麼,變數型態的道理就是一樣的。

另外,如果你想伸入討論有關型態長度的事情,是不是開個專版來討論會更合適呢?
有些大大回答的真不錯,但因為不符主題的關係讓我無法下手給予標記點數,甚為困擾。
作者 : sunyear(coco) VC++卓越專家C++頂尖高手貼文超過2000則
[ 貼文 2421 | 人氣 1485 | 評價 6060 | 評價/貼文 2.5 | 送出評價 5 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2016/6/6 下午 01:10:53
>我的意思是你提出了 macro 就是等於 "放棄使用" 不固定大小的一般形別,用 macro "替代"
這是以W蓋全!
如果這樣推論可以成立,
那如果在VC程式中因為要接收來自另一個裝置的結構資料,所以該結構宣告成#pragma pack(1)來取消alignment。
那就等於放棄使用memory alignment嗎?
還有其它千百個結構在使用預設的memory alignment。
取消了一個結構使用alignment,為什麼就等於放棄alignment?
那使用了一個unsigned int等於放棄使用int嗎?


>至於是否要把一般形別真正從 C++ 拿掉,我想會有很大的爭議,但我覺得也無妨,不是
>有 uint32_t 這樣的東西嗎,若要用 macro 得自己為各平台寫 macro,還不如用 uint32_t
uint32_t也是用typdef去定義,其功能相當於我的用macro去定義。
兩者是等價的,但若你要說typedef比較好,我可以贊成。前面我說的macro就改成typedef
但同樣的道理.有uint32_t不表示放棄了原來不固定的型別。只是在程式需要固定寬度的資料上才使用。
另外,不是所有的編譯器都有提供像uint32_t的定義(在stdint.h)。
沒有的話,自己寫一下固定寬度的標頭檔,也很簡單(五分鐘可完成)。
對一個程式員來說,不會一天到晚換編譯器,真的換編譯器,也不一定要改寫固定寬度的標頭檔。
真的要改寫,就那五分鐘,改完後相同的編譯器就可一直延用,算是很小很小的負擔。


>還有另一種選擇是用大數,形別會有這種多麻煩是因同樣是整數卻有很多種,若用大數就簡單多了,
>不管怎樣去實作它,只要中繼資料格式統一就行了
雖然沒規定,但int型別在編譯器中會設定成目標CPU運算上比較快速的最大寬度,通常會是暫存器或是累加器的寬度。
只為了統一型別選擇用大數,可能會犧牲效率和浪費不必要的記憶空間。
或許在記憶體寬裕和高運算速度的PC上,你會覺得who care。
但不要忘了,世界還有很多不同的CPU和應用。
在embeded系統裡,運算速度和記憶體,到目前為止,還是程式員必需考慮的。
作者 : sunyear(coco) VC++卓越專家C++頂尖高手貼文超過2000則
[ 貼文 2421 | 人氣 1485 | 評價 6060 | 評價/貼文 2.5 | 送出評價 5 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2016/6/6 下午 01:14:04
>雖然沒規定,但int型別在編譯器中會設定成目標CPU運算上比較快速的最大寬度
這句話修正一下:
雖然沒規定,但int型別在編譯器中會設定成目標CPU"效率考量下最合理的寬度"
作者 : ozzy123(ozzy) VC++優秀好手資訊類作業求救卓越專家C++卓越專家貼文超過4000則人氣指數超過30000點
[ 貼文 4499 | 人氣 37262 | 評價 11100 | 評價/貼文 2.47 | 送出評價 49 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2016/6/6 下午 03:35:07
macro without semantics
作者 : sunyear(coco) VC++卓越專家C++頂尖高手貼文超過2000則
[ 貼文 2421 | 人氣 1485 | 評價 6060 | 評價/貼文 2.5 | 送出評價 5 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2016/6/6 下午 04:45:23
>macro without semantics
我不是同意使用typedef比較好了嗎?
這應該不是討論重點。
我的重點是,不固定寬度的type有其道理,就算不管相容性木不宜做改變。
程式有需要確定寬度的型別,可以簡單的克服(macro,typedef 都是.typedef比較好?OK!)
作者 : ozzy123(ozzy) VC++優秀好手資訊類作業求救卓越專家C++卓越專家貼文超過4000則人氣指數超過30000點
[ 貼文 4499 | 人氣 37262 | 評價 11100 | 評價/貼文 2.47 | 送出評價 49 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2016/6/6 下午 10:31:15
size of elementary data types is not an issue. it just a part of programming language , but their implementations should be decided by compiler writers.
作者 : sunyear(coco) VC++卓越專家C++頂尖高手貼文超過2000則
[ 貼文 2421 | 人氣 1485 | 評價 6060 | 評價/貼文 2.5 | 送出評價 5 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2016/6/6 下午 11:54:27
>size of elementary data types is not an issue ... but their implementations should be decided by compiler writers.
通常情況如此,但有些情況programmer必需確定型別的寬度。
要不然,就不會有很多編譯器會有stdint.h提供固定型別的頭檔了。
除了前面討論到的經由網路或其它通訊互傳資料需要確定的型別寬度外,尚有很多的應用會需要定義固定寬度的型別。
舉個例子,如為防資料溢位之錯誤發生,需要確認用之資料型別之寬度。
又例如,要把收到資料存入 ring buffer。
這個ring buffer的型別寬度若剛是是buffer的大小,不但在程式撰寫很方便,效率上也高。
(下一個個存放位置,只管+1,不用管溢位)
這時就需要確認ring buffer索引變數的型別寬度。
作者 : ozzy123(ozzy) VC++優秀好手資訊類作業求救卓越專家C++卓越專家貼文超過4000則人氣指數超過30000點
[ 貼文 4499 | 人氣 37262 | 評價 11100 | 評價/貼文 2.47 | 送出評價 49 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2016/6/7 上午 08:21:48
http://pubs.opengroup.org/onlinepubs/009695399/basedefs/stdint.h.html
作者 : ozzy123(ozzy) VC++優秀好手資訊類作業求救卓越專家C++卓越專家貼文超過4000則人氣指數超過30000點
[ 貼文 4499 | 人氣 37262 | 評價 11100 | 評價/貼文 2.47 | 送出評價 49 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2016/6/7 上午 09:05:02
http://linux.die.net/include/stdint.h
作者 : kennytsai(Kenny) C++卓越專家貼文超過500則
[ 貼文 720 | 人氣 2903 | 評價 2840 | 評價/貼文 3.94 | 送出評價 140 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
主題發起人ice_emissary註記此篇回應為很有道理 2016/7/28 下午 11:40:05
後面樓歪了,但我還是想回應一下提問:
「起初在第一份程式見到 unsigned char 的寫法時,覺得當初寫這程式的人一定是個白痴」

1. 本人有10年以上的程式經驗,以我過往的作法,如果需要定義字串時,我也是使用 unsigned char。
2. 如其他前輩所言,如果能確認所有的字串皆為「英文」,則宣告 char 也無妨,不過,一旦有中文碼在內,就「有可能」出現處理錯誤。
3. 不瞞你說,就是因為吃過 char 的虧,所以後來,我一定全部宣告成 unsigned char。
4. 事實上,只要是緩衝區式的陣列(非關字串),我也全部設為 unsigned char,以避免「不小心」的錯誤。

上述「有可能」、「不小心」所指的,其實就在於「有號」跟「無號」的差別,我僅簡單的說明如下:
a. 當你進行「算數」運算時,因 char 的 bit7 代表正負號,所以擴展成 int 時,會跟你想的不同。如果是unsigned char,則單純前面補零。
b. 當你進行「邏輯」運算時,因為 char 的 bit7 代表正負號,所以進行右移運算時,結果會跟你想的不同。如果是unsigned char,則單純右移。
c. 從硬體(CPU)的角度來看,其實並沒有所謂的 signed bit,這些解讀、都是編譯器做的。Compiler 按照既定的規範,進行既定的「擴展」、「運算」、「調整」等,只要你稍不留神,就「有可能」、「不小心」出錯。但是,如果你宣告成 unsigned char,那麼,compiler 的處理邏輯就比較接近CPU的作法,且結果跟一般人的認知相同,這也是為何,寧可被罵白痴,也要宣告成 unsigned char 的原因。
作者 : sunyear(coco) VC++卓越專家C++頂尖高手貼文超過2000則
[ 貼文 2421 | 人氣 1485 | 評價 6060 | 評價/貼文 2.5 | 送出評價 5 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
主題發起人ice_emissary註記此篇回應為很有道理 2016/7/29 上午 01:52:55
>從硬體(CPU)的角度來看,其實並沒有所謂的 signed bit,這些解讀、都是編譯器做的
大部份的CPU都有有號運算的指令,所以有所謂的signed bit喔。
作者 : ice_emissary(燃燒的大地) 貼文超過200則
[ 貼文 408 | 人氣 0 | 評價 1890 | 評價/貼文 4.63 | 送出評價 18 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2016/7/29 下午 01:23:36
多謝前輩的回應。

只是我認為如果是因為 signed/unsigned 會對某些中文碼的處理造成問題而把所有字串宣告為 unsigned char* 的話,似乎是弊大於利,
因為和語言標準、習慣不同,所以使用上會處處不便。

若是我的話,在我需要對字串內的字碼進行某些字碼處理時,我會像這樣做:

// 介面上仍然使用一般的字串宣告,因為是語言慣例,
// 況且使用者也不關心我們對字碼怎麼做事。
void big5_proc_func(char *str)
{
    // 然後在內部的處理中,我才把字串轉型成對我比較方便且不易出錯的型態。
    // 這樣就兼顧到了內、外的使用方便性。
    unsigned char *array = (unsigned char*) str;
    ......
}

static
void big5_internal_util(unsigned char *str)
{
    // 當然,有些時候也會在函數的介面直接宣告 unsigned 字串,
    // 但是這個函式一定是我的字碼處理模組內部使用的函式,而不是對外的介面。
    // 這是因為這函式外面的人用不到,而內部的呼叫使用若還要一直轉型反而不自然。
    ......
}

> 4. 事實上,只要是緩衝區式的陣列(非關字串),我也全部設為 unsigned char,以避免「不小心」的錯誤。

以我的話,這時我會用 uint8_t 來宣告。
事實上,位元組陣列和字元陣列在使用上的意義已經不一樣了,雖然底層可能是一樣的原理。
作者 : ice_emissary(燃燒的大地) 貼文超過200則
[ 貼文 408 | 人氣 0 | 評價 1890 | 評價/貼文 4.63 | 送出評價 18 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2016/7/29 下午 01:28:50
補充一下。

我的意思總結就是,如果沒有其他因素,只是為了字碼處理的原因的話,因該在適當的階層以下才轉型為 unsigned char 來處理,
而不是讓 unsigned char 無限制的擴張到整個專案,造成一般使用的不便、以及 bug 的溫床(因為充斥轉型敘述)。
而且我相信字串的一般性宣告、處理、和使用才是使用頻率更高的用途吧!
作者 : ozzy123(ozzy) VC++優秀好手資訊類作業求救卓越專家C++卓越專家貼文超過4000則人氣指數超過30000點
[ 貼文 4499 | 人氣 37262 | 評價 11100 | 評價/貼文 2.47 | 送出評價 49 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2016/7/29 下午 05:44:08
https://en.wikipedia.org/wiki/Arithmetic_logic_unit
ALU logic circuit
作者 : ozzy123(ozzy) VC++優秀好手資訊類作業求救卓越專家C++卓越專家貼文超過4000則人氣指數超過30000點
[ 貼文 4499 | 人氣 37262 | 評價 11100 | 評價/貼文 2.47 | 送出評價 49 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2016/7/29 下午 05:59:32
http://stackoverflow.com/questions/5793740/how-does-cpu-do-subtraction
 板主 : simula
 > C++ - 討論區
 - 最近熱門問答精華集
 - 全部歷史問答精華集
 - C++ - 知識庫
  ■ 全站最新Post列表
  ■ 我的文章收藏
  ■ 我最愛的作者
  ■ 全站文章收藏排行榜
  ■ 全站最愛作者排行榜
  ■  月熱門主題
  ■  季熱門主題
  ■  熱門主題Top 20
  ■  本區Post排行榜
  ■  本區評價排行榜
  ■  全站專家名人榜
  ■  全站Post排行榜
  ■  全站評價排行榜
  ■  全站人氣排行榜
 請輸入關鍵字 
  開始搜尋
 
Top 10
評價排行
C++
1 Raymond 13050 
2 青衫 4760 
3 simula 4690 
4 coco 4030 
5 白老鼠(Gary) 3670 
6 ozzy 2540 
7 Ben 2250 
8 Anderson 1960 
9 windblown 1650 
10 Kenny 1560 
C++
  專家等級 評價  
  一代宗師 10000  
  曠世奇才 5000  
  頂尖高手 3000  
  卓越專家 1500  
  優秀好手 750  
Microsoft Internet Explorer 6.0. Screen 1024x768 pixel. High Color (16 bit).
2000-2019 程式設計俱樂部 http://www.programmer-club.com.tw/
0.296875