在阅读了许多关于C++中C风格转换的答案后,我仍有一个小问题。我能否对内置类型使用C风格转换,如
long x = (long)y;
,或者它仍被认为是不好和危险的?uint32_t n = ((uint32_t(buf[0]) << 24) |
(uint32_t(buf[1]) << 16) |
(uint32_t(buf[2]) << 8) |
(uint32_t(buf[3]) ));
在这里使用static_cast
会掩盖算术操作,而这才是重要的事情。(注意:如果sizeof(uint32_t) <= sizeof(unsigned int)
,这些转换是不必要的,并且现在已经是一个安全的假设,但我仍然更喜欢显式。)(是的,我可能应该将此操作分解为be32_to_cpu
内联助手,但我仍会以相同的方式编写代码。)
static_cast
在数值类型之间的转换方面是相同的。 - zwolreinterpret_cast
隐藏为 C 风格的转换。如果您要转换的类型是您认为是整数类型的指针,则会发生这种情况。嗯,在我们开始这个讨论之前,我感觉我有点在抓住稻草...现在我想,我刚刚描述的情况是唯一的情况,而不是更多潜在的程序员错误可以在转换为数字类型时被捕获。 - PeterSWstatic_cast
通常用于类类型。因此,在数字上应用 static_cast
看起来很奇怪",这听起来像是个人期望,似乎没有任何事实依据。 - François Andrieux我能想到一种合法使用C风格转换的情况:
// cast away return value to shut up pedantic compiler warnings
(void)printf("foo\n");
在我看来,在使用标准库函数和STL时,对于内置类型进行C风格转换是可以的,并且能够使代码更易读。
在我工作的公司中,我们使用最高级别(4级)警告来编译代码,因此我们会收到有关每个小型类型转换的警告......所以我在这些情况下使用C风格转换,因为它们更简短、不那么冗长并且很有意义。
for (int i = 0; i < (int)myvec.size(); i++)
{
// do something int-related with i
}
float val = (float)atof(input_string);
但是,如果它是在可能会更改的代码(例如库)中,则使用static_cast<>()更好,因为您可以确保编译器在类型更改且转换不再有意义时出错。此外,如果只使用C样式,那么在代码中搜索转换是不可能的。 " static_cast<mytype>(
" 很容易搜索。 :)
考虑到上下文,我认为这可能是可以的。例如:
/* Convert -1..1 to -32768..32767 */
short float_to_short(float f)
{
return (short)(max(-32768.f, min(32767.f, f * 32767.f)));
}
我更喜欢使用传统的C语言强制类型转换的情况是将字节缓冲区转换为不同的有符号性。许多API具有不同的约定,实际上并没有“正确答案”,在进行转换的上下文中,这种转换并不危险,因为代码只需要与使用的库组合一样跨平台。
我想给出一个具体的例子,我认为这样做很好:
unsigned char foo[16];
lib1_load_foo(key);
lib2_use_foo((char*)key);
但是对于其他任何情况,如果需要强制类型转换,它可能会产生潜在的副作用,这应该引起注意,并且使用C++风格(可以说是丑陋的)的强制类型转换是正确的选择。而如果不需要强制类型转换,则不要使用强制类型转换。
int convertDoubleToInt(double)
这样的函数颠覆了类型系统。但这基本上就是static_cast<int>(myDouble)
所做的。真正颠覆类型系统的是const_cast
和reinterpret_cast
,而不是另外两个转换。 - Ruslanstatic_cast<int>(some_double)
并不会破坏类型系统。但是,一般情况下的static_cast
可以破坏类型系统,例如将void*
转换为T*
(这会破坏类型系统,因为它不执行值转换;相反,它断言了类型系统无法验证的内容)。对于转换,我强烈建议使用T{obj}
语法,因为它使意图更清晰。不过,这也不是绝对可靠的(std::vector<…>{}
不执行转换...)。 - Konrad RudolphT{}
。缩小转换可能需要使用static_cast
来突出显示它们。 - Konrad Rudolph