如何将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】:

严格来说,由于严格别名违规,您的代码的行为是未定义的。

在实践中,如果intfloat 的大小相同(它们在许多桌面平台上,尽管有一些推动将int 移动到64 位),那么代码将运行而不会出错。虽然要重新迭代,但从标准 C++ 的角度来看,绝对不能保证这一点。

但你仍然应该修复它。直接分配float 数组是明智之举:

float* f_buffer = (float*) calloc (500, sizeof (float));

【讨论】:

为什么要保留calloc?这实际上并没有像使用 UB 一样生成一个数组。 @NathanOliver:因为我不想让 OP 不得不追查所有 free 电话。 实际上,其他发帖者提出的几种解决方案也有效,因为它们意味着 cppcheck 消息消失了!我选择这个作为答案是因为它在精神上更接近原始代码。我也不喜欢寻找免费电话。毫无疑问,这是否真的是正确的 c++ 方法是有争议的。从纯 c++ 的角度来看,“新”语法似乎是最正确的。 @didjek:如果您可以走 C++ 路线,那么 std::vector&lt;float&gt;(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指针转换为浮点指针的主要内容,如果未能解决你的问题,请参考以下文章

C++:如何获取浮点指针的地址并将其转换为 void**

如何将简单指针转换为固定大小的多维数组?

如何将文件指针 ( FILE* fp ) 转换为文件描述符 (int fd)?

如何将文件描述符(int fd)转换为文件指针(FILE * fp)

将指针转换为 int

C\C++指针变量怎么赋值给普通变量。