2014-10-05 64 views
4

我想了解有關uint8_t與字符,可移植性,位操縱,最佳實踐,事件狀態等的情況。您是否瞭解關於該主題的良好閱讀?如何使用uint8_t而不是char?

我希望做字節IO。但是當然char比uint8_t有更復雜和更微妙的定義;我認爲這是引入stdint頭的原因之一。

但是,我在多次使用uint8_t時遇到了問題。幾個月前,曾經,因爲iostreams沒有爲uint8_t定義。是不是有一個C++庫做真正定義好的字節IO,即讀寫uint8_t?如果不是,我認爲沒有需求。爲什麼?

我最近頭痛從這個代碼失敗編譯莖:

uint8_t read(decltype(cin) & s) 
{ 
    char c; 
    s.get(c); 
    return reinterpret_cast<uint8_t>(c); 
} 

error: invalid cast from type 'char' to type 'uint8_t {aka unsigned char}' 

爲什麼出錯?如何使這項工作?

+4

嗯。改用static_cast <>。 – 2014-10-05 12:49:34

+4

'decltype(cin)'似乎很瘋狂。你真的想'std :: istream&'那裏,沒有別的。 – 2014-10-05 12:51:12

+0

static_cast通過可能使用運行時轉換來保留數字值,如果我沒有弄錯,我想保留確切的位序列(我正在讀取磁盤的MBR) – peterf 2014-10-05 12:56:15

回答

2

一般,攜帶方便,往返,正確的方法是:

  1. 你的API中要求所有字節值可以與最多8位表示,
  2. 使用char佈局兼容性,signed charunsigned char以及
  3. 根據需要將unsigned char轉換爲uint8_t

例如:

bool read_one_byte(std::istream & is, uint8_t * out) 
{ 
    unsigned char x; // a "byte" on your system 
    if (is.get(reinterpret_cast<char *>(&x))) 
    { 
     *out = x; 
     return true; 
    } 
    return false; 
} 

bool write_one_byte(std::ostream & os, uint8_t val) 
{ 
    unsigned char x = val; 
    return os.write(reinterpret_cast<char const *>(&x), 1); 
} 

一些說明:規則1個保證值可以是往返uint8_tunsigned char之間轉換而不丟失信息。規則2意味着我們可以對unsigned char變量使用iostream I/O操作,即使它們是以char的形式表示的。

我們也可以使用is.read(reinterpret_cast<char *>(&x), 1)代替is.get()作對稱。 (通常使用read,對於大於1的流計數,錯誤也需要使用gcount(),但這不適用於此)。

與往常一樣,您絕不能忽略I/O操作的返回值。這樣做總是程序中的一個錯誤。

+0

這與問題相關,因爲在問題的評論中討論了使用static_cast的情況,但OP說它不適合,就像你一樣。但我不明白爲什麼。 – 2014-10-05 13:51:26

+0

@NeilKirk static_cast reinterpret_cast和dynamic_cast主要用於記錄程序員的意圖,對代碼的實際影響可能在某些情況下是相同的,但並非在所有情況下都是一樣的 – peterf 2014-10-06 18:13:26

+0

@Kerrek編譯器錯誤的技術原因是什麼?爲什麼我不能鎮定類型系統並重新解釋char爲uint8_t?爲什麼我需要一個完整的指針來獲取單個字節? – peterf 2014-10-06 18:21:23

0

幾個月前,一次,因爲iostreams沒有爲uint8_t定義。

uint8_t幾乎只是unsigned char的typedef。事實上,我懷疑你可以找到一臺機器。

uint8_t read(decltype(cin) & s) 
{ 
    char c; 
    s.get(c); 
    return reinterpret_cast<uint8_t>(c); 
} 

使用decltype(cin)代替std::istream沒有任何優勢可言,這是混亂的只是一個潛在來源。 return - 聲明中的演員不是必需的;將一個char轉換爲一個unsigned char暗中作品。

幾個月前,一次,因爲iostreams沒有爲uint8_t定義。

他們是。不是針對uint8_t本身,而是針對它實際表示的類型。操作員>>超載爲unsigned char。此代碼的工作:

uint8_t read(istream& s) 
{ 
    return s.get(); 
} 

由於unsigned charchar可以互爲別名,你也可以直接reinterpret_cast任何指針char字符串的unsigned char*並與工作。

如果你想要最便攜的方式可以看看Kerreks的答案。

+0

「由於無符號字符和字符可以互相混淆」,您可以說明? – 2014-10-05 13:24:20

+0

@NeilKirk根據[basic.lval]/10,你可以通過'char'或'unsigned char'類型的glvalue來訪問對象的存儲值。所以你可以通過'unsigned char'類型的glvalue來訪問'char'數組的任何存儲元素。你也可以通過這樣一個glvalue來修改這些元素,並再次用'char'-glvalue來訪問它們。 – Columbo 2014-10-05 14:05:33

相關問題