C ::在函数中抛出指针,丢失数据?

时间:2017-04-05 14:04:02

标签: c pointers syntax casting

我有一个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”,“指针”,“铸造”,“改变价值”,我拉起的帖子遍布地图。有时候最好直接问你的问题。

1 个答案:

答案 0 :(得分:1)

在您的代码中

 return (float*)a;

违反了严格的别名规则。 int *float *不会互为别名,因此投射会使代码无效

intfloat具有不同的对齐要求,因此基本上您无法通过指向int的指针引用为float保留的内存位置(反之亦然)并期望一切都落实到位。

引用标准的相关部分,章节§6.5/ P7

  

对象的存储值只能由具有其中一个的左值表达式访问   以下类型:88)

     

- 与对象的有效类型兼容的类型,

     

- 与对象的有效类型兼容的类型的限定版本

     

- 对应于有效类型的有符号或无符号类型   对象,

     

- 对应于合格版本的有符号或无符号类型的类型   有效的对象类型,

     

- 包含其中一种上述类型的聚合或联合类型   成员(包括,递归地,子集合或包含的联合的成员),或

     

- 字符类型。

以及更多章节§6.3.2.3/ P7

  

指向对象类型的指针可以转换为指向不同对象类型的指针。如果   对于引用的类型,结果指针未正确对齐 68),行为是   未定义。 [....]