12

在调试我们的一些代码(C++)时,我发现了这个:

inline std::string BufferToStr(
    const unsigned char* buffer,
    int index,
    size_t length)
{
   std::string retValue(reinterpret_cast<const char*>(&buffer[index], length));
   return retValue;
}

这段代码的问题(忽略了指针和字符串长度检查的缺失)是 的右括号reinterpret_cast被放在length了应该放在后面的时候&buffer[index]。起初我认为这是编译器的问题(使用 VS2013),但在使用 VS2012 和 gcc 4.6.3 成功编译它之后,我得出的结论是由于某种原因这是允许的。该代码不会在 Windows 或 Linux 上运行,因为长度参数用作指针。

所以我的问题是为什么会编译?查看文档reinterpret_cast我找不到任何文档说您可以将逗号分隔的值列表传递给它以及它将如何处理它。

4

5 回答 5

12

reinterpret_cast接受一个表达式。括号中的内容是一个表达式 - 带有两个子表达式的“,”运算符,它将计算最后一个子表达式的结果。

于 2013-08-16T09:13:02.200 回答
7

这是由于c/c++ 中的逗号运算符。代码(一个表达式):

(&buffer[index], length)

相当于(&buffer[index] 无效):

(length)

所以你的代码相当于:

inline std::string BufferToStr(const unsigned char* buffer, int index, size_t length)
{
   std::string retValue(reinterpret_cast<const char*>(length));
   return retValue;
}
于 2013-08-16T09:16:02.353 回答
4

这是逗号运算符。它计算逗号两边的表达式,但返回右边表达式的结果。

编译器不抱怨的原因是因为您简单地告诉编译器表达式(类型size_t)的结果应该被视为const char*表达式。就是reinterpret_cast这样,它允许将几乎任何类型转换为几乎任何其他类型,无论它可能多么愚蠢。

于 2013-08-16T09:13:09.840 回答
3
reinterpret_cast < new_type > ( expression )        

reinterpret_cast接受一个表达式。这里有一个逗号运算符,它计算两边的表达式并返回右手表达式。

其实表达式(&buffer[index], length)等价于(length)这里。

请参阅:http: //msdn.microsoft.com/en-us/library/zs06xbxh.aspxhttp://en.wikipedia.org/wiki/Comma_o​​perator了解逗号运算符的解释。

总而言之,在这里你告诉你的编译器将 a size_t(表达式的结果)转换为 aconst char*并且它可以做到这一点。

于 2013-08-16T09:15:58.307 回答
2

这是启用警告很重要的原因之一,它可能会帮助您自己解决这个问题。使用gcc并运行-Wall,这是我收到的警告:

 warning: left operand of comma operator has no effect [-Wunused-value]
 std::string retValue(reinterpret_cast<const char*>(&buffer[index], length));
                                                                  ^

您可以查看现场示例

警告告诉我们一开始我们使用的是逗号运算符,这可能有点令人费解,但它不是一个函数调用,如我们在这个人为的示例reinterpret_cast中看到的那样,如果不使用括号,这将无法工作,而是一个表达式Postfix部分C++ 标准草案的表达式 postfix-expression语法包含:5.2

postfix-expression:
   ...
   reinterpret_cast < type-id > ( expression )
   ...

我们可以expression在参数中使用 an ,所以comma operator它是完全有效的。

于 2013-08-16T11:53:41.030 回答