如何将int指针转换为浮点指针
Posted
技术标签:
【中文标题】如何将int指针转换为浮点指针【英文标题】:How to cast int pointer to float pointer 【发布时间】:2020-01-29 16:14:33 【问题描述】:我正在对一个包含许多类似于下面的强制转换的库运行 cppcheck (c++11):
// Allocates various buffers
int* i_buffer = (int*) calloc (500, sizeof (int));
float* f_buffer = (float*) i_buffer;
对于这些演员表,我看到以下消息:
"portability","invalidPointerCast","在具有不兼容二进制数据表示的整数*和浮点*之间进行转换。"
执行上述类型转换的正确方法是什么?以上面显示的方式投射指针的潜在后果是什么?
【问题讨论】:
使用 c++ 强制转换。 'reinterpret_cast' 在这种情况下 编译器的消息似乎完全合法。您能否提供一些背景信息来说明为什么要这样做?这对我来说似乎很糟糕的代码(但也许有一些理由写这个?) @BЈовић 这是一个常见的误解(不排除我自己)reinterpret_cast
允许您在任意类型之间进行转换,但实际上只有一个相当有限的情况列表 reinterpret_cast
不会将您直接带入未定义的行为领域
没有。首先(int*) calloc (500, sizeof (int));
不会在整数上生成数组。它只是分配内存。使用它将是未定义的行为。如果您使用float* f_buffer = (float*) i_buffer;
以便可以像浮点数一样遍历那些不存在的整数,这也是非法的,因为它违反了严格的别名规则。再多的演员也无法解决任何问题。这是 C 代码(除了 calloc 转换),不应在 C++ 代码中使用。
@user253751 existing 是一个编译时概念,lifetime 是一个运行时概念。在编译时,您已经通过声明、新表达式、更改活动联合成员或创建临时对象来创建对象。然后,在运行时,生命周期在获取存储并完成初始化后开始。如果您在编译时没有对象(如 OP 的示例),那么在运行时没有对象可以激活。
【参考方案1】:
如何将 int 指针转换为浮点指针
使用重新解释演员表。
但不要尝试这样做,因为重新解释的指针不会有用。
执行上述类型转换的正确方法是什么?
显示的演员表本身已经很好地定义了;做这样的演员是没有用的。
如果你需要分配一个浮点数组,你可以使用下面的代替:
std::vector<float>(500);
【讨论】:
reinterpret_cast 可以通过编译器(与现有代码一样)。但是,对于 cppcheck,我会收到相同的警告消息。 @didjek 是的。它通过编译器是因为程序格式正确。但是 cppcheck 进一步检查了程序,并发现强制转换没有用。【参考方案2】:严格来说,由于严格别名违规,您的代码的行为是未定义的。
在实践中,如果int
和float
的大小相同(它们在许多桌面平台上,尽管有一些推动将int
移动到64 位),那么代码将运行而不会出错。虽然要重新迭代,但从标准 C++ 的角度来看,绝对不能保证这一点。
但你仍然应该修复它。直接分配float
数组是明智之举:
float* f_buffer = (float*) calloc (500, sizeof (float));
【讨论】:
为什么要保留calloc
?这实际上并没有像使用 UB 一样生成一个数组。
@NathanOliver:因为我不想让 OP 不得不追查所有 free
电话。
实际上,其他发帖者提出的几种解决方案也有效,因为它们意味着 cppcheck 消息消失了!我选择这个作为答案是因为它在精神上更接近原始代码。我也不喜欢寻找免费电话。毫无疑问,这是否真的是正确的 c++ 方法是有争议的。从纯 c++ 的角度来看,“新”语法似乎是最正确的。
@didjek:如果您可以走 C++ 路线,那么 std::vector<float>(500);
将很难被击败,尽管您可能需要更改代码结构以保持该向量在范围内,另外,您需要找到所有free
电话。并非我们所有人(包括我)都拥有一个由完美的 C++17 代码组成的代码库——我的代码库是慢慢修复到 C++11 标准的一堆东西。这就是为什么我喜欢人们先学习 C99,这样他们才会有进化感。
All: @NathanOliver 确实在这里提出了一个重要的观点——从技术上讲,行为在 C++ 中仍然是未定义的(calloc
不是创建 object 的方法),尽管时尚是将其视为 C++ 标准中的缺陷。在商业上,如果我有一个 C++ 编译器,我会切换编译器供应商。【参考方案3】:
通过 new 使用旧式 C 数组也是合法的(这是 C++ 标准):
float* f_buffer = new float[500];
注意调整该内存的释放以适应:
delete [] f_buffer;
应始终避免类型转换,以保持代码干净并允许编译器验证代码的正确性。
【讨论】:
new
语法是 C++,而不是 C
@AnonymousAnonymous:确实如此,而且语言标签是 C++。但是这个答案应该指出你不能使用free
来释放分配给new
的内存:所以远离calloc
可能会引入错误,除非你像兔子一样追捕所有相应的free
调用。跨度>
@Bathsheba 是的,我知道 - 只是想指出,这不是 old style C array
。措辞可能会让人们感到困惑
您好,也感谢您的建议,它也有效。看来我对芭丝谢芭的提议发表了评论。
你是对的,但“旧样式”是指 C 样式数组,而不是新语法。对于删除释放我添加了一个注释。以上是关于如何将int指针转换为浮点指针的主要内容,如果未能解决你的问题,请参考以下文章
如何将文件指针 ( FILE* fp ) 转换为文件描述符 (int fd)?