【问题标题】:Difference between static_cast<char*> and (char*)static_cast<char*> 和 (char*) 之间的区别
【发布时间】:2011-11-11 09:03:45
【问题描述】:

这是我的第一个问题:)

我有一堆文件,我打开它如下图所示;

ifstream in ( filename,  ios :: binary | ios :: in ) 

然后,我希望在 unsigned int hold 中保存 2 字节数据;

unsigned int hold;
in . read(static_cast<char *>(&hold), 2); 

这对我来说似乎是正确的。但是,当我用

编译它时
g++  -ansi -pedantic-errors -Werror - -Wall  -o main main.cpp 

编译器发出错误

error: invalid static_cast from type ‘unsigned int*’ to type ‘char*’ 

其实我已经通过将static_cast改成(char*)解决了这个问题,也就是

unsigned int hold;
in . read((char*)(&hold), 2); 

我的问题是:

  • static_cast&lt;char*&gt;(char*) 之间有什么区别?
  • 我不确定使用(char*) 是否更安全。如果你有足够的知识,你能告诉我那个话题吗?

注意:如果您有更好的想法,请帮助我,以便我可以改进我的问题?

【问题讨论】:

标签: c++ file


【解决方案1】:

static_cast 是比隐式 C 样式转换更安全的转换。如果您尝试转换一个与另一个不兼容的实体,那么static_cast 会给您一个编译时错误,这与隐式 c 样式转换不同。

static_cast 在这里给你一个错误,因为你想说的是取一个int 并尝试将它放入char,这是不可能的。 int 需要比 char 占用更多的内存,并且无法以安全的方式进行转换。

如果你还想实现这个,你可以使用reinterpret_cast,它可以让你对两种完全不同的数据类型进行类型转换,但是不安全。
使用reinterpret_cast 获得的唯一保证是,如果将结果转换回原始类型,您将获得相同的值,但没有其他安全保证。

【讨论】:

  • +1 用于解释,但我会在此处提及 reinterpret_cast
【解决方案2】:
  • 首先 - 您可以轻松搜索 _cast 并找到任何 c++ 演员表。搜索 c 风格的演员表要困难得多。
  • second - 如果你使用 c++ casts,你需要选择正确的一个。在你的情况下,它是reinterpret_cast
    c 风格的演员可以做任何事情。

您也可以在这里查看:http://www.cplusplus.com/doc/tutorial/typecasting/,了解不同 c++ 类型转换的差异。我强烈建议只使用 c++ casts。这样,您以后可以轻松地找到并检查它们,并且您不得不考虑您在那里实际在做什么。这提高了代码质量!

【讨论】:

    【解决方案3】:

    您应该使用reinterpret_cast&lt;char *&gt; 而不是static_cast&lt;char *&gt;,因为数据类型不相关:例如,您可以在指向子类的指针之间转换为超类,或在intlong 之间转换,或者在void * 和任何指针之间,但unsigned int *char * 不是“安全的”,因此您不能使用static_cast 来做到这一点。

    不同之处在于,在 C++ 中,您有各种类型的强制转换:

    • static_cast 用于“安全”转换;

    • reinterpret_cast 用于“不安全”转换;

    • const_cast 用于删除const 属性;

    • dynamic_cast 用于向下转换(将指针/引用从超类转换为子类)。

    C 风格的演员(char *)x 可以表示以上所有这些,所以它不像 C++ 演员那样清楚。此外,用 grep 查找 C++ 风格的转换很容易(只需 grep 查找 _cast),但很难搜索所有 C 风格的转换。

    【讨论】:

    • const_cast 仅用于转换const,但也用于不太为人所知/使用的volatile
    • @AndreaBergia:注意const_cast 也可以添加 constvolatile 限定符。 (当然,这并不是说在很多情况下这都是有用的。)
    • C 风格的演员表永远不会与dynamic_cast 相同。 (除了static_castdynamic_cast 都与隐式转换做同样的事情。)并且static_cast 并不总是“安全的”:例如,它可以从 Base 转换为 Derived 引用/指针,当对象实际上不是 Derived。
    【解决方案4】:

    static_cast 在这里是非法的;你在不相关的人之间投射 指针类型。让它编译的解决方案是使用 reinterpret_cast(在这种情况下,(char*) 解析为)。 当然,这会告诉您代码不可移植,事实上, 除非你在做一些非常低级的工作,否则可能不会工作 在所有情况下都正确。

    当然,在这种情况下,您正在读取原始数据,并声称它是 unsigned int。它不是;什么读取输入是原始数据,你 根据 写入文件时使用的格式。 (没有这样的东西 未格式化的数据。只是具有未记录、未指定或 未知格式。 “未格式化”的输入和输出 iostream 旨在读取和写入您格式化的char 缓冲区 手动。这里需要reinterpret_cast 是一个明确的警告 你的代码有问题。 (也有例外, 当然,但它们很少。)

    【讨论】:

      【解决方案5】:

      在使用 ifstream 或 ofstream 或 fstream 进行二进制文件 I/O 期间,您通常会遇到这些错误。问题是这些流具有采用const char* 的方法,而您拥有的是其他类型的数组。您想将数组作为二进制位写入文件。

      执行此操作的传统方式是使用旧式强制转换(char*),它基本上只是说我将其视为(char*) 的任何指针。 pedantic/strict mode 不鼓励旧风格的演员表。为了消除这些警告,C++11 等价物是 reinterpret_cast&lt;const char*&gt;

      我想说,如果您正在执行二进制文件 I/O,那么您已经知道事情可能是可移植的,也可能不是可移植的,这取决于您如何将文件保存在一个操作系统中并在另一个操作系统中读取。这完全是另一个问题,但是,不要被reinterpret_cast&lt;const char*&gt; 吓到,因为如果您想将字节写入文件,就必须这样做。

      【讨论】:

        猜你喜欢
        • 2018-11-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-02-19
        • 2014-11-07
        • 2011-02-25
        • 1970-01-01
        相关资源
        最近更新 更多