2014-10-05 27 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

相关问题