【问题标题】:C pointer behavior not understoodC 指针行为不理解
【发布时间】:2018-02-16 10:37:17
【问题描述】:

我有一个简单的结构,loc

typedef struct
{
  long blk;
  int offset;
} loc;

在函数avl_isnadd中,它被传入为:

int
avl_isnadd (old_loc, old_isn, isn)
loc *old_loc;
int old_isn, isn;
  {
    int next_isn;
    loc *this_loc;
    printf("\n{avl_isnadd} - old_loc-> blk = %d, old_loc->offset = %d\n", old_loc->blk, old_loc->offset);
    this_loc->blk = old_loc->blk;
    this_loc->offset = old_loc->offset;
    printf("\n{avl_isnadd} - this_loc->blk = %d, this_loc->offset = %d\n", this_loc->blk, this_loc->offset);
     next_isn = avl_isnget (this_loc);
     return next_isn;
}

在 avl_isnget 中,我们有:

int
avl_isnget (myLoc)
loc *myLoc;
  {
    printf("\n{avl_isnget} - MyLoc->blk = %d, myLoc->offset = %d\n", myLoc->blk, myLoc->offset);
    return 0;
   }

控制台上的结果是:

{avl_isnadd} - old_loc-> blk = 1, old_loc->offset = 512

{avl_isnadd} - this_loc->blk = 1, this_loc->offset = 512


{avl_isnget} - MyLoc->blk = 1485457792, myLoc->offset = 512

我在这里缺少什么?我不明白为什么 avl_isnget 应该有 myLoc->blk

的不同值

【问题讨论】:

  • 您没有为this_loc 分配任何空间。只要您执行this_loc->blk = old_loc->blk;,您就会调用未定义的行为。
  • 那么,如果我将其定义为loc this_loc,我该如何做赋值并将其作为指针传递给函数呢?
  • 你需要分配一些内存。买一本更新的 C 书——老式的参数列表在 30 年前就已经过时了。
  • 自 28 年以来,这已过时且强烈反对!买一本最近的书,这也将有助于理解指针和内存分配!
  • 如果将其定义为loc this_loc,则使用&得到this_loc的指针,即:&this_loc。你在使用 C 文档吗?

标签: c pointers arguments


【解决方案1】:

您没有为this_loc 分配任何空间,因此一旦您执行this_loc->blk = old_loc->blk;,您就在调用undefined behavior。您可以在自动存储中或从堆中为this_loc 分配空间。我将演示自动存储选项,因为考虑到提供的代码(使用更新的语法),我发现它更可取:

自动存储选项:

int
avl_isnadd (loc *old_loc, int old_isn, int isn)
{
    int next_isn;
    loc this_loc; // don't make it a pointer. this declaration will allocate space for
                  // the struct in automatic storage (in many implementations,
                  // the stack) whose scope exists only in this function
    printf("\n{avl_isnadd} - old_loc-> blk = %ld, old_loc->offset = %d\n", old_loc->blk, old_loc->offset);  // printf uses the %ld specifier for a signed long 
    this_loc.blk = old_loc->blk;  // change the accessor operator from -> to .
    this_loc.offset = old_loc->offset;
    printf("\n{avl_isnadd} - this_loc.blk = %ld, this_loc.offset = %d\n", this_loc.blk, this_loc.offset);
    next_isn = avl_isnget (this_loc); // Simply pass the entire struct to the avl_isnget function.
    return next_isn;
    // this_loc goes out of scope (pops off the stack) and you're done with it
}

然后将您的 avl_isnget 函数更改为

int
avl_isnget (loc myLoc)
{
    // myLoc is now a local copy of the this_loc struct that you passed in.
    // Since this function doesn't modify the struct loc passed in, there's
    //no real point in passing in a pointer. A local copy will do just fine for printing
    printf("\n{avl_isnget} - MyLoc.blk = %ld, myLoc.offset = %d\n", myLoc.blk, myLoc.offset);
    return 0;
}

另一种选择是将空间分配为loc* this_loc = malloc(sizeof(loc)); 并从那里开始,但是根据提供的代码,没有理由这样做。避免内存管理,除非您有 good reason to do so

【讨论】:

    【解决方案2】:

    this_loc 是一个指向无效内存地址的指针。事实上这个程序应该会崩溃。

    this_loc = old_loc 也应该可以。

    【讨论】:

      猜你喜欢
      • 2021-12-19
      • 2018-11-06
      • 1970-01-01
      • 2013-01-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多