【问题标题】:Truncation of pointers when casting投射时截断指针
【发布时间】:2014-03-18 04:36:15
【问题描述】:

我有以下情况:

  • 函数 list_split 返回一个 (list_t *)
  • 我调用 list_split 并将返回值转换为 (void **)
  • 函数返回 11054a2b8,但接收值的 var 得到 1054a2b8
  • 所以,看起来 (list_t *) 有 8 个字节,但 (void *) 只有 4 个字节

代码如下:

typedef struct node_s *list_t;

typedef struct node_s {
  void *el;
  list_t tail;
} node_t;


list_t *list_split(list_t list, void **head)
{
  if ( list ) {
    *head = list->el;
    printf( " &list->tail = %p", &list->tail ));
    return &list->tail;
  }
  else {
    *head = (void *)NULL;
    return (list_t *)NULL;
  }
}

foo()
{
  void **list;

  list = (void **)list_split(*list, &ent);
  printf( "list = %p", list ) );
}

还有输出:

&list->tail = 11054a2b8
list = 1054a2b8

【问题讨论】:

  • 您的代码中可能存在未定义的行为:您使用 *list 作为第一个参数调用 list_split,但 list 是一个未初始化的指针(指向指针),因此取消引用它会导致未定义的行为。我希望您在真实代码中正确初始化它?也许您应该编辑您的问题以包含short and self-contained example
  • 为什么不直接打印 sizeof(void*) 和 sizeof(list_t*) ?
  • 如果你的 void* 是 4 个字节,那么你的 list_t* 必须是 4 个字节..

标签: c pointers casting 32bit-64bit


【解决方案1】:

完全不清楚这段代码的作用。尽管如此,它具有未定义的行为,因为变量 list 未在函数 foo 中初始化,但它(更准确地说是 *list)在函数 list_split 中进行了测试

foo()
{
  void **list;  // What is the value of list?

  list = (void **)list_split(*list, &ent); // What is the value of *list?
  printf( "list = %p", list ) );
}


list_t *list_split(list_t list, void **head)
{
  if ( list ) {   // What is the value of list?
//...

下次尝试提供一个简单的完整编译代码示例,每个人都可以测试它。

【讨论】:

  • 列表已初始化。完整的声明是:void **list = &clients;。 clients 指向一个链表。很抱歉缺少信息。
【解决方案2】:

我发现了问题:

  • foo 和 *list_split* 在不同的文件中(应该共享一个信息)
  • 在定义 foo 的文件中没有 *list_split* 的原型

代码在 32 位中运行良好。只是当我将它重新编译为 64 位时,问题才出现。我认为这是因为没有原型,编译器假定返回 4 字节。

感谢您的回答。我应该分享所有信息,但我认为这无关紧要。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-03
    • 2014-09-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多