cout和printf的压栈与a++和++a

cout和printf的压栈与a++和++a

  预先声明:这个问题在不同的编译器下,结果也相应不同。
以下内容转载自:http://blog.youkuaiyun.com/kzzhr/article/details/8482657
先看一段代码,猜猜会是什么输出:
x=1;   printf("%d %d\n",x,x++);  
x=1;   printf("%d %d\n",x++,x);  
x=1;   printf("%d %d %d\n",x,x++,x);  
x=1;   printf("%d %d %d %d\n",x,++x,x++,x);

答案:
  1. 2 1  
  2. 1 2  
  3. 2 1 2  
  4. 3 3 1 3

  看到这里,你会发现,有时看起来是从左往右算,有时候是从右往左算,有时候还是从乱序算。。是不是有些郁闷呢。

其实,在处理printf时,压栈顺序为从右往左,也就是说从右往左的计算(“计算”不等于“输出”)。

在计算时,遇到x++会记录此时的x的值作为最后的输出结果。遇到x和++x的时候则不会将此时的计算结果作为最终的输出,只会修改x的值,在最终输出的时候都输出x的值(所以++x和x的结果总是一样的)。

为什么会是这个样子呢?参见某高手解释吧:

      对于a++的结果,是有ebp寻址函数栈空间来记录中间结果的,在最后给printf压栈的时候,再从栈中把中间结果取出来;而对于++a的结果,则直接压寄存器变量,寄存器经过了所有的自增操作。 (来源:http://www.zzzj.com/html/20090609/71613.html)


以下内容转载自:http://www.zzzj.com/html/20090609/71613.html

int main() 
{ 
int a = 1; 
printf("b = %d\tc = %d\td = %d\te = %d\tf = %d\tg = %d\n", 
a++, ++a, a++, ++a, a++, ++a ); 

return 0; 
} 
结果:

b = 6 c = 7 d = 4 e = 7 f = 2 g = 7

对结果如是理解:压栈从右往左,GFEDCB的顺序,压栈前要对a进行计算,由于FDB是a++所以2、4、6,而剩下是++a,所以要等a自增计算完,所以都是7。 
有一个问题是:编译器怎么做到的呢? 
Go to Dessembly说出了迷底。对于a++的结果,是有ebp寻址函数栈空间来记录中间结果的,在最后给printf压栈的时候,再从栈中把中间结果取出来;而对于++a的结果,则直接压寄存器变量,寄存器经过了所有的自增操作。 
这就是a++和++a的压栈的区别。


同样的情况也存在于cout。

例如下面的例子:

#include<iostream>
using namespace std;
int main()
{
    int a = 1;
    cout<< "b = " << a++ << " c = " << ++a << " d = " << a++ << " e = " << ++a << " f = " << a++ << " g = " << ++a;
    // printf("b = %d\tc = %d\td = %d\te = %d\tf = %d\tg = %d\n", a++, ++a, a++, ++a, a++, ++a );
    return 0;
}

coutprintf 计算表达式的先后未定义行为;从左到右从右到左都合法,先中间再两边也完全可以。先计算表达式的值然后压栈,然后再输出,所以不同的编译器如vcgcc的表现行为是不一样的。对于如上程序 不同的编译器结果是不一样的!!!



<think>好的,我现在需要处理用户关于MySQL删除数据后如何恢复的问题。首先,我要回忆一下之前学过的相关知识,并结合提供的引用内容来整理步骤。 用户的问题明确,他们想知道在误删除数据后有哪些恢复方法。根据提供的引用,有几个关键点需要注意: 1. **使用备份恢复**:这是最直接的方法,如果有最近的备份,可以直接还原数据库。引用[3]提到如果表结构被删除,可以通过备份还原表结构,然后再恢复数据。这可能涉及到全量备份增量日志的应用,如引用[2]中提到的先恢复全量,再处理增量日志。 2. **利用binlog日志**:如果没有备份,但开启了binlog,可以通过分析binlog找到删除操作的位置,然后导出相关SQL进行恢复。引用[1][2]都提到了这一点,尤其是需要确定误操作的时间点或位置点,然后使用mysqlbinlog工具导出并跳过错误的DELETE语句。 3. **第三方工具**:如果前两种方法不可行,可能需要使用专业的数据恢复工具来扫描磁盘,提取未被覆盖的数据。不过这可能比较复杂,且成功率取决于数据是否被覆盖。 接下来,我需要将这些步骤结构化,确保用户能够按照清晰的流程操作。同时,要提醒注意事项,比如停止写入操作、备份的重要性等。另外,示例命令可能会帮助用户更好地理解操作步骤,比如如何从binlog导出SQL,如何应用增量日志。 需要检查是否有遗漏的细节,比如如何确定binlog的位置点,或者如何还原备份文件的具体命令。引用[4]中的mysqldump命令示例可能对用户有帮助,可以提及备份时使用的参数如何恢复备份。 最后,生成相关问题时,要覆盖用户可能进一步想知道的内容,比如预防措施、binlog的配置、不同恢复方法的优缺点等。</think>### MySQL删除数据后恢复方法 在MySQL中误删除数据后,恢复策略主要依赖**备份文件****二进制日志(binlog)**,具体操作步骤如下: --- #### 一、立即停止写入操作 1. **停止数据库服务**(可选): 防止新数据覆盖磁盘上的删除记录,提高恢复成功率。 2. **保留当前环境**: 不要重启服务器或执行其他写入操作。 --- #### 二、通过备份恢复数据 若存在定期备份,恢复流程如下: 1. **还原最近的全量备份** 使用`mysqldump`备份文件还原数据库: ```bash # 解备份文件(如使用gzip缩) gzip -d /opt/backup/ops_2023-10-01.sql.gz # 导入备份 mysql -uroot -p < ops_2023-10-01.sql ``` 此操作会覆盖现有数据,需谨慎操作[^4]。 2. **应用增量日志(如有)** 若开启了binlog,需将全量备份后的增量日志恢复到误删前的状态: ```bash # 导出指定时间段的binlog为SQL文件 mysqlbinlog --start-datetime="2023-10-01 10:00:00" --stop-datetime="2023-10-01 11:00:00" /var/lib/mysql/binlog.000002 > increment.sql # 删除文件中误操作的DELETE语句后执行恢复 mysql -uroot -p < increment.sql ``` 此方法可精确恢复到误删前的时间点[^2]。 --- #### 三、通过binlog直接恢复(无备份时) 若未备份但开启了binlog,按以下步骤操作: 1. **定位误删事件的位置或时间** 查询binlog内容找到DELETE语句: ```bash mysqlbinlog --base64-output=decode-rows -v /var/lib/mysql/binlog.000003 ``` 记录误删操作的`# at 12345`(位置点)或`#221001 10:30:00`(时间戳)。 2. **导出恢复用的SQL文件** 跳过误删的DELETE语句,导出其他操作: ```bash # 按位置点导出(推荐) mysqlbinlog --stop-position=12344 /var/lib/mysql/binlog.000003 > recovery.sql mysqlbinlog --start-position=12346 /var/lib/mysql/binlog.000003 >> recovery.sql # 按时间点导出 mysqlbinlog --stop-datetime="2023-10-01 10:30:00" /var/lib/mysql/binlog.000003 > recovery.sql mysqlbinlog --start-datetime="2023-10-01 10:31:00" /var/lib/mysql/binlog.000003 >> recovery.sql ``` 3. **执行恢复** ```bash mysql -uroot -p < recovery.sql ``` 此方法需确保binlog格式为`ROW`或`MIXED`,否则可能无法解析具体数据[^1]。 --- #### 四、使用第三方工具(极端情况) 若未开启binlog且无备份,可尝试: 1. **磁盘文件恢复工具**(如`extundelete`)扫描未被覆盖的`.ibd`文件。 2. **专业数据恢复服务**:需联系数据库修复公司。 --- #### 注意事项 1. **定期备份**:建议使用`mysqldump -B --master-data=2`备份并记录binlog位置[^4]。 2. **开启binlog**:在`my.cnf`中配置: ```ini [mysqld] log-bin=mysql-bin binlog_format=ROW ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值