C Interfaces and Implementations 关于setjmp,longjmp和volatile

问题出自:
C Interfaces and Implementations:Chapter 4 Exceptions and Assertions
书中提到c语言中setjmp.h里的setjmp(jmp_buf env)longjmp(jmp_buf env,int val)
以前从来没有见到过这两个函数,看完这一章也不是很明白这两个函数到底有什么用,回来百度之

int setjmp(jmp_buf envbuf);

c++ reference :
Save calling environment for long jump
This macro with functional form fills env with information about the current state of the calling environment in that point of code execution, so that it can be restored by a later call to longjmp.

Calling longjmp with the information stored in env restores this same state and returns the control to that same point (the call to setjmp), which is evaluated as a particular non-zero value.

The state of the calling environment includes the values of all accessible objects, except those of automatic duration local to the function which do not have volatile-qualified types and which change before the call to longjmp; these have indeterminate values.

The invocation of setjmp shall be an expression statement by itself, or be evaluated in a selection or iteration statement either as the (potentially negated) entire controlling expression or compared against an integer constant expression. Otherwise, it causes undefined behavior.

Return Value:
This macro may return more than once: A first time, on its direct invocation; In this case it always returns zero.
When longjmp is called with the information set to env, the macro returns again; this time it returns the value passed to longjmp as second argument if this is different from zero, or 1 if it is zero.
翻译一下:
为longjump存储调用函数时的上下文环境
setjmp(env)函数会在调用时保存当时的上下文环境,以便于后面longjmp(env,val)函数的调用
‘上下文环境’包括:所有可以访问的对象,除了那些没有volatile属性的函数内的局部变量和longjmp被调用之前被更改的变量。
第三段是setjmp的一些使用条件
返回值:
第一次调用setjmp时一定返回0,
之后调用longjmp时setjump也会返回值,值为longjmp的第二个参数

void longjmp(jmp_buf envbuf, int val)

Restores the environment to the state indicated by env, evaluating the setjmp expression that filled env as val.

The function never returns to the point where it has been invoked. Instead, the function transfers the control to the point where setjmp was last used to fill the env, and evaluates the whole expression as val (unless this is zero, in which case it evaluates as value of 1).

If env was not filled by a previous call to setjmp or if the function with such call has terminated execution, it causes undefined behavior.

In C++, the implementation may perform stack unwinding that destroys objects with automatic duration. If this invokes any non-trivial destructors, it causes undefined behavior.
上面一大堆简单来说就是:
longjmp函数中的参数envbuf是由setjmp函数所保存过的堆栈环境,参数val设置setjmp函数的返回值。longjmp函数本身是没有返回值的,它执行后控制流跳转到保存envbuf参数的setjmp函数调用,并由setjmp函数调用返回,此时setjmp函数的返回值就是val。

下面是实例:


#include <stdio.h> 
#include <setjmp.h>  
 jmp_buf buf; 
 banana(){ 
    printf("in banana() \n"); 
    longjmp(buf,1); 
     printf("you'll never see this,because i longjmp'd"); 
 } 
 main() 
{ 
    if(setjmp(buf)) 
        printf("back in main\n"); 
    else{ 
        printf("first time through\n"); 
        banana(); 
    } 
 }

输出是这样的:

first time through
in banana()
back in main

仔细看一下应该更能体会这对函数的作用
setjmp/longjmp的最大用处是错误恢复,类似try …catch…
他们的功能比goto强多了,goto只能在函数体内跳来跳去,而setjmp/longjmp可以在到过的所有位置间。

Volatile
参考:
http://www.cnblogs.com/yc_sunniwell/archive/2010/06/24/1764231.html
简单来说就是声明了volatile属性的变量不会因为编译器优化代码而对这个代码本来的意图产生影响

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 重新启用非隧道接口和IPv6隧道接口的下载功能,可以通过以下步骤完成: 1. 首先,打开计算机上的网络设置界面。这可以通过在开始菜单中搜索“网络设置”或单击任务栏中的网络图标来完成。 2. 在网络设置界面中,找到并点击“更改适配器选项”。这将打开一个新的窗口,显示所有可用的网络适配器。 3. 在适配器窗口中,找到您要重新启用IPv6下载功能的非隧道接口。非隧道接口通常以以太网或无线局域网(Wi-Fi)的形式显示。右键单击该接口,然后选择“属性”。 4. 在接口属性窗口中,找到并选择“Internet 协议版本 6 (IPv6)”选项。确保此选项已选中,然后单击“属性”。 5. 在IPv6属性窗口中,确保“自动获取IP地址”选项处于启用状态。如果该选项已禁用,请将其重新启用。然后单击“确定”保存更改。 6. 对于IPv6隧道接口,您可以按照相似的步骤启用下载功能。找到相关的隧道接口,如隧道适配器或隧道接口隧道6to4。右键单击该接口,选择“属性”,然后在IPv6属性窗口中启用或重新启用“自动获取IP地址”选项。 重新启用非隧道接口和IPv6隧道接口的下载功能后,您应该能够正常下载使用IPv6协议的内容和应用程序。请注意,可能需要重新启动计算机才能使更改生效。 ### 回答2: 为了在非隧道接口和IPv6隧道接口上重新启用IPv6下载,需要按照以下步骤进行操作: 1. 确定系统是否支持IPv6:首先,检查操作系统是否支持IPv6功能。大多数现代操作系统都支持IPv6,但某些较旧的操作系统版本可能不支持。在确认支持IPv6之后,可以在继续前进之前进行适当升级或更新。 2. 检查非隧道接口的IPv6状态:通过查看网络设置或使用命令行工具(如ipconfig(Windows)或ifconfig(Linux)),确保非隧道接口启用了IPv6。如果IPv6被禁用,可以通过网络设置或命令行工具启用它。 3. 检查IPv6隧道接口的状态:如果使用了IPv6隧道接口(如6to4或Teredo隧道),请检查隧道连接的状态。通过查看网络设置或使用适当的命令行工具,确保隧道接口正确配置,并且处于可用状态。 4. 重新启用IPv6下载:一旦确认非隧道接口和IPv6隧道接口都启用了IPv6,就可以开始下载IPv6内容。打开适当的网络应用程序,如浏览器或下载管理器,然后在目标网址中输入IPv6地址以获取所需的下载内容。 总结起来,在系统支持IPv6的前提下,需要确保非隧道接口和IPv6隧道接口都启用了IPv6,并使用网络应用程序在IPv6地址上下载所需内容。以上是关于如何重新启用非隧道接口和IPv6隧道接口下载的简要说明。 ### 回答3: 要重新启用非隧道接口和IPv6隧道接口下载,需要按照以下步骤进行操作: 1. 首先,打开计算机的控制面板。可以在开始菜单中搜索控制面板并打开。 2. 在控制面板中,选择“网络和Internet”选项。 3. 在网络和Internet选项中,选择“网络和共享中心”。 4. 在网络和共享中心中,查找并选择“更改适配器设置”。 5. 在适配器设置中,你将看到计算机的网络连接列表。找到要重新启用IPv6的非隧道接口和IPv6隧道接口。 6. 选择要重新启用的接口,右键点击并选择“属性”。 7. 在接口属性中,找到“Internet协议版本6 (TCP/IPv6)”选项。将其选中并点击“属性”按钮。 8. 在IPv6属性中,确保选择了“获取IPv6地址自动”或“使用以下IPv6地址”选项,并在相应的字段中填入正确的IPv6地址信息。 9. 确认设置后,点击“确定”按钮保存更改。 10. 重复以上步骤,以重新启用其他非隧道接口和IPv6隧道接口的下载。 通过以上步骤,你可以重新启用非隧道接口和IPv6隧道接口的下载功能,并确保其正常运行。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值