问题描述
当我将带有 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 上,所以内存中的内容是分开的,代码位置不会改变。