我正在学习指针的工作方式,但是我不理解此代码中的一件事。 在void *函数中返回int就像一个超级按钮一样,但返回float却没有。
ndarray
[xval, yval, ...]
答案 0 :(得分:6)
这两个函数都调用undefined behaviour,因为返回类型和return
语句中表达式的类型不匹配。
关于似乎为什么起作用的信息,请阅读有关未定义行为的信息。
也就是说,在所有警告均视为错误的地方打开编译器警告,并设置该代码甚至不应编译为生成二进制文件,因为它包含约束违规,应该会产生诊断(警告)
相关说明:
引用C11
,第6.8.6.4章
[...]如果表达式中有一个 type与出现的函数的返回类型不同,值为 就像分配给具有函数返回类型的对象一样进行转换。
以及关于简单分配的内容,请参见第6.5.16.1节简单分配:
约束
应满足以下条件之一:
- 左操作数具有原子,合格或不合格的算术类型,而右操作数具有算术类型;
- 左操作数具有与右类型兼容的结构或联合类型的原子,合格或不合格版本;
- 左操作数具有原子,限定或不限定的指针类型,并且(考虑到左操作数在左值之后将具有的类型 转换),两个操作数都是指向合格或不合格的指针 类型的兼容类型,并且左侧指向的类型具有 右侧所指类型的所有限定词;
- 左操作数具有原子,限定或不限定的指针类型,并且(考虑到左操作数在左值之后将具有的类型 转换)一个操作数是一个指向对象类型的指针,另一个 是指向void的合格或不合格版本的指针,并且 左侧指向的类型具有指向该类型的所有限定符 靠右边
- 左操作数是原子,限定或不限定的指针,右是空指针常量;或
- 左边的操作数的类型是atomic,合格或不合格的_Bool,右边的是指针。
因此,您不能合法地将int
或float
分配给指针类型-这是一个约束冲突。
答案 1 :(得分:2)
问题是您尝试将浮点数转换为指针。
C没有指定任何有关指针格式的内容。这是因为C试图抽象所有可能的体系结构,并且某些体系结构具有非常罕见的表示指针的方式。例如,在Lisp机器上,内存位置,因此指针以segment:offset表示。同样,在哈佛体系结构中,它将数据区域的代码区域和指针对这些不同区域的编码方式分开。 C仅在函数指针与对象指针之间进行区分,而对指针对象中每一位的含义一无所知。
在您的计算机上整数很好地转换的事实只是一个机会。如果您的计算机有64个总线地址,而32位是整数,则返回的指针具有一定意义,并且看起来与整数“相等”,这仅意味着体系结构可能具有与指针相同的整数值表示形式。
现在,在您的代码中,浮点数将转换为指针,而从指针转换回浮点数。浮点数的表示形式定义为正负号/指数/尾数,但指针的表示形式未定义,并且可能发生未定义的行为。
答案 2 :(得分:0)
如果您仍然希望此方法起作用,则应返回指向float
的指针。但是,在函数中执行此操作会涉及一些堆分配。
代码可以像这样。我没有检查是否返回了真正的浮点数。这是你的任务
#include <stdio.h>
#include <stdlib.h>
void* square (const void* num);
int main() {
float *x, sq_int;
float value = 6;
x = square(&value);
printf("%f squared is %f\n", value, *x);
free(x);
return 0;
}
void* square (const void *num) {
float *result = malloc(sizeof(float));
*result = (*(float *)num) * (*(float *)num);
return ((float*)result);
}