我有一个C语法101问题。假设我有一个函数,它将一种指针作为参数并返回不同类型的指针,并且两个指针都指向调用函数内的相同数据。例如:
#include <stdio.h>
float* convertPtr(const int *a){
return (float*)a;
}
int main() {
float *ptrF;
int x = 5;
ptrF = convertPtr(&x);
printf("%d ::converted to:: %f\n", x, *ptrF);
return 0;
}
该计划的输出是:
5 ::converted to:: 0.000000
所以我对此感到有点困惑。原始数据在 main()内创建,不会更改。 convertPtr()函数永远不会改变数据,但只应更改指针的类型。
我还注意到,当我逐步浏览GDB上的代码时,指针(地址本身)不会改变:
Breakpoint 1, main () at exp.c:9
9 int x = 5;
(gdb) p &x
$3 = (int *) 0x7fffffffe224
...continue to after calling convertPtr()...
(gdb) p ptrF
$4 = (float *) 0x7fffffffe224
(gdb)
然而 值 指出数据有:
(gdb) p x
$8 = 5
(gdb) p *(&x) // sanity check
$9 = 5
(gdb) p *ptrF
$10 = 7.00649232e-45
(gdb)
那么......到底是什么?在我的convertPtr()函数之后,指针已经重铸,但指针的值没有改变......但解引用转换后的指针似乎指向垃圾数据。 (我假设。)
有人在这看到这个问题吗?假设我必须修复我的功能;我怎么做?感谢...
-ROA
PS:如果这是一个重复的问题,请道歉。我搜索了大约一个小时的“C”,“指针”,“铸造”,“改变价值”,我拉起的帖子遍布地图。有时候最好直接问你的问题。
答案 0 :(得分:1)
在您的代码中
return (float*)a;
违反了严格的别名规则。 int *
和float *
不会互为别名,因此投射会使代码无效。
int
和float
具有不同的对齐要求,因此基本上您无法通过指向int
的指针引用为float
保留的内存位置(反之亦然)并期望一切都落实到位。
引用标准的相关部分,章节§6.5/ P7
对象的存储值只能由具有其中一个的左值表达式访问 以下类型:88)
- 与对象的有效类型兼容的类型,
- 与对象的有效类型兼容的类型的限定版本
- 对应于有效类型的有符号或无符号类型 对象,
- 对应于合格版本的有符号或无符号类型的类型 有效的对象类型,
- 包含其中一种上述类型的聚合或联合类型 成员(包括,递归地,子集合或包含的联合的成员),或
- 字符类型。
以及更多章节§6.3.2.3/ P7
指向对象类型的指针可以转换为指向不同对象类型的指针。如果 对于引用的类型,结果指针未正确对齐 68),行为是 未定义。 [....]