c++ 如何将具有数据类型的变量传递给函数是法律的的?

zazmityj  于 2023-05-20  发布在  其他
关注(0)|答案(2)|浏览(69)

我目前正在研究DLL的一个非常具体的测量设备,这是所谓的“测力板”和先进的机械技术公司生产。它可以测量人站立或移动时产生的地面反作用力。这个DLL是用Visual C++编写的(正如程序员参考所说),由测力板制造商提供。
因此,有一个函数叫做fmDLLTransferFloatData。这就是它在DLL头文件中的声明方式:
int DLLExport fmDLLTransferFloatData(float *&data);
它返回一个int,并需要一个指向float数据的指针的引用。到目前为止一切顺利。下面是这个函数的奇怪部分,根据程序员参考,它必须在代码中使用的方式:

float *ptr;
int ret;

//getting the Data
ret = fmDLLTransferFloatData((float *&)ptr);

看一下论点的语法:((float *&)ptr)。而且它能工作。有人能解释一下这个syntaxis实际上是什么意思吗?
所以,正如我已经说过的,这个函数工作得很好,如果有人能向我解释这个奇怪的语法,我会很高兴的。

qoefvg9y

qoefvg9y1#

表达式(T)E(其中T是类型,E是表达式)是C风格的强制转换或显式类型转换。它将表达式E转换为类型T。在所有C的强制转换表达式中,它是允许最大转换集的表达式。
然而,它对你所展示的上下文毫无影响。如果ptrfloat*类型的变量,则表达式ptr(float *&)ptr是100%完全等价的。
所以你可以写ptr
事实上,使用C风格的强制转换(float *&)是一种不好的做法,因为它很容易导致严重的问题被忽视。不管ptr是什么类型,强制转换几乎总是成功的,但是如果它实际上不是float*,那么它几乎肯定会导致未定义的行为。但是编译器不会将其诊断为错误或警告,因为强制转换本质上是告诉编译器不要抱怨,不管它有多危险。
在C
中几乎从来不需要使用C风格的强制转换。C++有static_castconst_castreinterpret_cast,它们中的每一个只允许一个较小的转换子集,因此使用起来更具体,更安全。在大多数情况下,static_cast足以取代C风格的强制转换,在其他情况下必须格外小心。

nafvub8i

nafvub8i2#

感谢@user17732522的评论,我更正了答案中的一些内容。希望能更详细地解释
以下内容是相同的,因为表达式会自动将左值转换为对左值的引用。

ret = fmDLLTransferFloatData((float *&)ptr);
ret = fmDLLTransferFloatData((float *)ptr);
ret = fmDLLTransferFloatData(ptr);

此外,这些调用也将同样工作,并通过值传递函数声明:

int fmDLLTransferFloatData(float *);

而不是:

int fmDLLTransferFloatData(float *&);

DLL库编码器建议使用第一个版本的唯一可能原因是“文档”ptr本身在DLL函数中受到修改。但它并没有强制执行。它更像是一个评论。
这一行指明了被调用的函数来改变指针,而不仅仅是被指向的浮点数。

ret = fmDLLTransferFloatData((float *&)ptr);

显示指针被更改的示例代码:

#include <iostream>
float other_float = 42;
float orig{ 1 };
float* ptr{ &orig };

int fmDLLTransferFloatData(float*& ptr)
{
    ptr = &other_float;
    return 2;
}

//getting the Data
int main()
{
    int ret;
    std::cout << *ptr << '\n';
    ret = fmDLLTransferFloatData((float*&)ptr);
    std::cout << *ptr << '\n';
    return ret;
}

Compiler Explorer
如果函数被正确声明,甚至不需要强制转换:

int fmDLLTransferFloatData(float *&);

它可以被称为w/o cast:

ret = fmDLLTransferFloatData(ptr);

相关问题