无法理解如何将地址存储在 void * 中并使用 goto 跳转到它们

问题描述 投票:0回答:1

我正在阅读 GNU C 手册并阅读了有关 goto 语句的部分:

作为扩展,GCC 允许 goto 语句跳转到某个地址 由 void* 变量指定。为了使这项工作有效,您还需要 使用一元运算符 &&(不是 &)获取标签的地址。 这是一个人为的例子:

enum Play { ROCK=0, PAPER=1, SCISSORS=2 };
enum Result { WIN, LOSE, DRAW };

static enum Result turn (void) 
{
  const void * const jumptable[] = {&&rock, &&paper, &&scissors};
  enum Play opp;                /* opponent’s play */
  goto *jumptable[select_option (&opp)];
 rock:
  return opp == ROCK ? DRAW : (opp == PAPER ? LOSE : WIN);
 paper:
  return opp == ROCK ? WIN  : (opp == PAPER ? DRAW : LOSE);
 scissors:
  return opp == ROCK ? LOSE : (opp == PAPER ? WIN  : DRAW);
}

const
中的第二个
const void * const jumptable[]
是做什么用的?声明基本上就是
array of const pointers to const void
,对吧?但我不明白这意味着什么,抱歉,如果这听起来很愚蠢。

那么,&opp 是什么意思呢?该代码对其地址有何作用? select_option()是什么?

c goto
1个回答
0
投票

const
放置在指针
*
声明的右侧时,它使指针本身变为只读。如果放置在
*
左侧,则指向的数据是只读的。

当设计带有函数指针而不是标签的传统跳转表时,通常将表本身设置为只读。有两个原因:

  • 在运行时动态改变跳转位置可能是不可取的。通常您不想要或不需要那么大的灵活性。因此,跳转表应该在编译时设计并保持这种状态。有意或无意的写入应该被阻止。
  • 在嵌入式系统中,
    *  const
    只读限定符意味着跳转表将分配在非易失性闪存而不是RAM中。这意味着它被分配在真正的只读存储器中,而且还可以节省宝贵的 RAM - 在一般的微控制器编程场景中,RAM 比闪存更有价值。

那么,&opp 是什么意思?

我不能确定,因为你没有包含

select_option
函数,但它可能是这种性质的函数:

enum Play select_option (enum Play* p)
{
  *p = some_decision();
  return *p;
}

也就是说,函数会更改传递的变量,但也会返回它以方便函数调用。而不是用返回类型

void
来声明它,在这种情况下我们必须编写

select_option (&opp);
goto *jumptable[opp];

这无疑不是问题,因为代码更具可读性,并且“单行上的最多子表达式赢得价格”的编程形式是非常糟糕的做法。

一般来说,让一个函数通过多种方式返回相同的值(既作为返回值又作为参数之一)实际上被认为是有问题的 API 设计。但这是另一个故事了。

© www.soinside.com 2019 - 2024. All rights reserved.