C 是跨函数调用的标签地址相同

问题描述

当我将带有 GCC 标签标签地址存储为值扩展时,它们在不同深度调用中是否相同?

void *label = NULL;

int test() {
  if (label == NULL) {
    label = &&label_l;
  } else {
    goto *label;
  }
  
  return(test() + 1);
  
  label_l:
  return(0);
}

即使标签设置在不同的堆栈框架中,这也能工作吗?

解决方法

它们在不同深度调用中是否相同?

一般来说,是的。来自the documentation

如果包含函数被内联或克隆,则同一标签的 &&foo 表达式可能具有不同的值。如果程序依赖于它们始终相同,则应使用 __attribute__((__noinline__,__noclone__)) 来防止内联和克隆。如果在静态变量初始化器中使用 &&foo,则禁止内联和克隆。

在您的程序中,它没有用于静态变量初始值设定项,因此您的函数可能被内联或复制,并且标签将跳转到不同的函数 - 确保它不会发生。 (但即使您会执行 static void *label = &&label_l,我仍然会添加 __attribute__((__noinline__,__noclone__)) 以防止以后重构)。

一个真实的例子:protothreads 可以使用 labels as values 来存储要跳转到的 case 语句。

总的来说,不要使用标签作为值。如果您打算使用它,最好只将它用于自动局部变量。您提供的代码看起来像是对无法维护的意大利面条式代码的邀请。

即使标签设置在不同的堆栈帧中?

是的,堆栈帧无关紧要。我们生活在 (ok,"modified") Hardvard architecture 上,所以内存中的内容是分开的,代码位置不会改变。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...