返回错误值的函数,C 语言,使用 gcc Intel 编译器
我写这篇文章是因为我真的不知道为什么会发生这种情况。我知道如何纠正/绕过它,但我想知道发生这种情况的原因。我正在使用 C,我的编译器是在 Intel 机器上运行的 gcc 4.4.1 (TDM)。
关于浮点数的假设: - 符合 IEEE 754 标准 - 以 Big Endian 方式存储
假设我们有一个函数,它接收 4 个字节的数组并将它们作为浮点数返回。这就是该函数的目标。我们还可以说,例如,该函数要做的就是以“正确的顺序”获取字节,并且由于系统是小端字节序,因此它只会交换它们并将它们放入浮点数中以返回值。为了简单起见,我不包括对 NaN 或 INF 的任何检查,因为这不是这个问题的目的。
float testFunction(char* arr)
{
//this will be the float we return
float ret;
//let's just get a char pointer to the float so we can alter its byte values
char* c = (char*)&ret;
//just swap them so they conform with little endian byte order
c[0] = arr[3];
c[1] = arr[2];
c[2] = arr[1];
c[3] = arr[0];
//up to here if you debug and watch ret's value it is correct as it is supposed to be
return ret;
}
问题是在我使用该函数的任何地方......让我们像下面这样说
float f = testFunction(arr);
然后浮点 f 具有与您作为参数传递的字节完全不相关的浮点值。
成功解决这个问题的方法是声明一个接受浮点数作为参数的函数,并在函数内部给它一个值,如下所示:
void testFunction(char* arr,float* f)
{
char* c = ((char*)f)
c[0] = arr[3];
c[1] = arr[2];
c[2] = arr[1];
c[3] = arr[0];
}
但我的问题仍然是,为什么当我尝试返回值时会发生这种情况?我确实知道 float ret 是函数范围内的临时值,但 return 语句应该将其值复制到函数之外。难道不对吗? 我缺少什么?我想这一定是非常明显的事情。
I am writing this because I have really no idea why this is happening. I know how to correct it/go around it but what I would like to know is the reason this occurs. I am using C and my compiler is gcc 4.4.1 (TDM) running on an Intel machine.
Assumptions about floats: -Conform to the IEEE 754 standard
- Are stored in a Big Endian way
Let's assume we have a function taking in an array of 4 bytes and returning them as a float. That is the goal of the function. Let's also say that for example all the function will do is get the bytes in the "right order" and since the system is little endian it will just swap them and put them into the float to return a value. For simplicity's sake I don't include any checks for NaN or INF since this is not the purpose of this question.
float testFunction(char* arr)
{
//this will be the float we return
float ret;
//let's just get a char pointer to the float so we can alter its byte values
char* c = (char*)&ret;
//just swap them so they conform with little endian byte order
c[0] = arr[3];
c[1] = arr[2];
c[2] = arr[1];
c[3] = arr[0];
//up to here if you debug and watch ret's value it is correct as it is supposed to be
return ret;
}
The problem is wherever I use the function ... let's say like below
float f = testFunction(arr);
Then the float f has a completely irrelevant float value to the bytes you pass as parameters.
The way to succesfully go around this is to declare a function that accepts the float as a parameter and give it a value inside the function like so:
void testFunction(char* arr,float* f)
{
char* c = ((char*)f)
c[0] = arr[3];
c[1] = arr[2];
c[2] = arr[1];
c[3] = arr[0];
}
But still my question is, why does this happen when I try to return the value? I do understand that float ret is a temporary value inside the scope of the function but the return statement should copy its value outside of the function. Isn't it correct?
What am I missing? I guess it must be something really obvious.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
实际上,在这两种情况下,浮点数都应该具有“完全不相关”的值,除非您仔细制作该字符数组(例如来自
float
的memcpy
)。您不能只设置字节并希望它能够神奇地匹配您平台上的表示。
Actually in both cases the float should have a "completely irrelevant" value, unless you carefully craft that array of chars (for example
memcpy
from afloat
).You can't just set the bytes and hope it will magically match the representation on your platform.
我会说一些愚蠢的话。但请尝试初始化
ret
,例如float ret = 0;
。我不确定您是否可以一次初始化一个
char
变量“piecemail”,并将其视为针对 C 标准(和编译器)“初始化”I'll say something stupid. But try initializing
ret
, likefloat ret = 0;
.I'm not sure you can initialize a variable "piecemail" one
char
at a time and consider it to be "initialized" for the C standard (and the compiler)摇摆。由于类型转换,编译器无法识别
f
变量已更新。对于编译器来说,f
变量和c
指针之间没有链接。它不知道这是一个别名。正如在 ABI 中一样,浮点数在寄存器中返回,当它返回时,它应该从堆栈生成一个负载,但是当它看到
f
被统一化时,它不执行任何操作并返回用于该操作的寄存器的随机内容。如果您将
float
声明为易失性
,它应该会执行您所期望的操作。正如所说,这是一个疯狂的猜测。
WAG. Because of the typecast, the compiler doesn't recognize that the
f
variable has been updated. For the compiler there's no link between thef
variable and yourc
pointer. It doesn't know it's an alias.As in the ABI the float is returned in a register, it should generate a load from the stack when it does the
return
, but as it sees thatf
is unitialized, it does nothing and returns the random content of the register used for that.If you declare
float
asvolatile
it should do what you expect.As said, it's a wild a.. guess.