首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >善用后藤?

善用后藤?
EN

Code Review用户
提问于 2020-03-09 00:10:44
回答 2查看 159关注 0票数 -3

我想我可能在我的代码中遇到了goto的一个很好的使用。从我开始用C语言编程时,我就开始意识到goto就像召唤魔鬼一样,应该不惜一切代价避免使用goto。这是代码

代码语言:javascript
运行
复制
/*
    Attempts to get the physical address from a virtual one by 
    1. Consulting the TLB 
    2. Consulting the PageTable
    3. If both fail, request data be read into memory

    Returns the address of the requested virtual address in physical memory
*/
unsigned int getAddress(unsigned int virtualAddress)
{
    const unsigned int pageNumber = getPageNumber(virtualAddress);
    const unsigned int pageOffset = getPageOffset(virtualAddress);

    // first consult the TLB
    int frame = getFrameFromTLB(pageNumber);
    if (frame != SENTINEL)
    {
        TLBHits++;
        goto TLB_HIT;
    }

    // if a TLB miss occurs, consult page table
    frame = getFramePageTable(pageNumber);
    if (frame != SENTINEL)
    {
        goto PAGE_HIT;
    }

    //miss on tlb and page table, page fault occured
    pageFaults++;
    goto PAGE_FAULT;

PAGE_FAULT:
    //page table miss, value not in memory, request physical memory to load value
    frame = loadValueFromBackingStore(pageNumber);

    //update page table with new frame
    insertIntoPageTable(pageNumber, frame);

PAGE_HIT:
    insertIntoTLB(pageNumber, frame);

TLB_HIT:
    return frame * PAGE_SIZE + pageOffset;
} 

如您所见,代码有一个级联执行模式,而goto似乎很好地建模了这个模式。我想知道,在没有后藤的情况下,是否有一种干净且大小相似的方式来写这篇文章?这应该是我想做的事吗?

EN

回答 2

Code Review用户

回答已采纳

发布于 2020-03-09 01:18:46

代码语言:javascript
运行
复制
goto PAGE_FAULT;
PAGE_FAULT:

这段代码看起来就像一个巨魔。你当然可以重写它,不用使用gotos;你所要做的就是取消当你一开始插入gotos时必须翻转的条件。例如:

代码语言:javascript
运行
复制
    if (frame != SENTINEL) {
        goto PAGE_HIT;
    }
    pageFaults++;
    frame = loadValueFromBackingStore(pageNumber);
    insertIntoPageTable(pageNumber, frame);
PAGE_HIT:

可以用“结构化编程”的方式重写为

代码语言:javascript
运行
复制
    if (frame == SENTINEL) {
        pageFaults++;
        frame = loadValueFromBackingStore(pageNumber);
        insertIntoPageTable(pageNumber, frame);
    }

你的整个功能归结为:

代码语言:javascript
运行
复制
unsigned int getAddress(unsigned int virtualAddress)
{
    const unsigned int pageNumber = getPageNumber(virtualAddress);
    const unsigned int pageOffset = getPageOffset(virtualAddress);

    int frame = getFrameFromTLB(pageNumber);
    if (frame == SENTINEL) {
        frame = getFramePageTable(pageNumber);
        if (frame == SENTINEL) {
            pageFaults += 1;
            frame = loadValueFromBackingStore(pageNumber);
            insertIntoPageTable(pageNumber, frame);
        }
        insertIntoTLB(pageNumber, frame);
    } else {
        TLBHits += 1;
    }
    return frame * PAGE_SIZE + pageOffset;
} 
票数 7
EN

Code Review用户

发布于 2020-03-11 14:15:30

从永无休止的goto争论中得出的共识是:“是的,有些情况下,你可以在无条件地向下分支时使用goto,但这些案例也可以不带goto编写。”

因此,您的代码并不可怕,但也不太漂亮--它看起来就像旧的"on error goto.“BASIC使用的错误处理模式。无论如何,所有的跳跃都是多余的,使代码不必要地难以阅读。

由于您正在几个地方更新全局变量,您最好重写函数如下:

代码语言:javascript
运行
复制
unsigned int getAddress(unsigned int virtualAddress)
{
  const unsigned int pageNumber = getPageNumber(virtualAddress);
  const unsigned int pageOffset = getPageOffset(virtualAddress);

  if(getFrameFromTLB(pageNumber) != TLB_HIT)
  {
    if(getFramePageTable(pageNumber) != PAGE_HIT)
    {
      //page table miss, value not in memory, request physical memory to load value
      frame = loadValueFromBackingStore(pageNumber);

      //update page table with new frame
      insertIntoPageTable(pageNumber, frame);
    }
  }

  return frame * PAGE_SIZE + pageOffset;
}

这假设被调用的函数将更新全局变量,而TLB_HIT等则是带有错误代码的枚举。还有其他方法你也可以重写它。

票数 1
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/238595

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档